SICP Checking eval is a thunk? - functional-programming

In Sec 4.2.2 of SICP,
(define (list-of-arg-values exps env)
(if (no-operands? exps)
'()
(cons (actual-value (first-operand exps) env)
(list-of-arg-values (rest-operands exps)
env))))
Calls
(define (actual-value exp env)
(force-it (eval exp env)))
Calls
(define (force-it obj)
(if (thunk? obj)
(actual-value (thunk-exp obj) (thunk-env obj))
obj))
As per the thunk structure
(define (delay-it exp env)
(list 'thunk exp env))
(define (thunk? obj)
(tagged-list? obj 'thunk))
If the first operand was a thunk , why does it check whether the eval is a thunk?
If the operand is a thunk it would be like "list thunk exp `env". but why is it testing if the eval is a thunk?
Can someone please explain how this part works together along with an example

As commented By Sylwester,
When eval is lazy what eval is returning is always a thunk. When you need to force it it might not be enough to force only one level so it forces as long as the value is a thunk. The second it isn't it is the actual forced value fully evaluated. Imagine the expression (+ a b) needs to evaluate +, a, b before it can actually apply so with lazy evaluation the expression won't actually be run until you force it and then it will evaluate at least 4 things (a and b might be stuff needs forcing too)

The return value of the evaluation gets forced. An object can only be forced, if it is a chunk. So it is checked, if it is a chunk.

Related

Clojure's disappearing reflection warnings

A simple reflection warning example:
lein repl
user=> (set! *warn-on-reflection* true)
true
user=> (eval '(fn [x] (.length x)))
Reflection warning, NO_SOURCE_PATH:1:16 - reference to field length can't be resolved.
#object[user$eval2009$fn__2010 0x487ba4b8 "user$eval2009$fn__2010#487ba4b8"]
I want to make this into a function. But where do reflection warnings go?
//clojure/compile.java 63
RT.errPrintWriter()
.format("Reflection warning, %s:%d:%d - reference to field %s can't be resolved.\n",
SOURCE_PATH.deref(), line, column, fieldName);
//clojure/RT.java 269
public static PrintWriter errPrintWriter(){
Writer w = (Writer) ERR.deref();
//clojure/RT.java 188
final static public Var ERR =
Var.intern(CLOJURE_NS, Symbol.intern("*err*"),
new PrintWriter(new OutputStreamWriter(System.err), true)).setDynamic();
Ok so they go to System.err. Lets capture it's output:
(def pipe-in (PipedInputStream.))
(def pipe-out (PipedOutputStream. pipe-in))
(System/setErr (PrintStream. pipe-out))
(defn reflection-check [fn-code]
(binding [*warn-on-reflection* true]
(let [x (eval fn-code)
;_ (.println (System/err) "foo") ; This correctly makes us return "foo".
n (.available pipe-in)
^bytes b (make-array Byte/TYPE n)
_ (.read pipe-in b)
s (apply str (mapv char b))]
s)))
However, calling it gives no warning, and no flushing seems to be useful:
(println "Reflection check:" (reflection-check '(fn [x] (.length x)))) ; no warning.
How can I extract the reflection warning?
You have correctly discovered how *err* is initialized, but since vars are rebindable this is no guarantee about its current value. The REPL often rebinds it to something else, e.g. a socket. If you want to redirect it yourself, you should simply rebind *err* to a Writer of your choosing.
Really I'm not sure your approach would work even if *err* were never rebound. The Clojure runtime has captured a pointer to the original value of System.err, and then you ask the Java runtime to use a new value for System.err. Clojure certainly won't know about this new value. Does the JRE maintain an extra level of indirection to allow it to do these swaps behind the scenes even for people who have already captured System.err? Maybe, but if so it's not documented.
I ran into a similar problem a while back and created some helper functions modelled on with-out-str. Here is a solution to your problem:
(ns tst.demo.core
(:use tupelo.core tupelo.test) )
(defn reflection-check
[fn-code]
(let [err-str (with-err-str
(binding [*warn-on-reflection* true]
(eval fn-code)))]
(spyx err-str)))
(dotest
(reflection-check (quote (fn [x] (.length x)))))
with result:
-------------------------------
Clojure 1.10.1 Java 14
-------------------------------
err-str => "Reflection warning, /tmp/form-init3884945788481466752.clj:12:36
- reference to field length can't be resolved.\n"
Note that binding and let forms can be in either order and still work.
Here is the source code:
(defmacro with-err-str
"Evaluates exprs in a context in which *err* is bound to a fresh
StringWriter. Returns the string created by any nested printing
calls."
[& body]
`(let [s# (new java.io.StringWriter)]
(binding [*err* s#]
~#body
(str s#))))
If you need to capture the Java System.err stream, it is different:
(defmacro with-system-err-str
"Evaluates exprs in a context in which JVM System/err is bound to a fresh
PrintStream. Returns the string created by any nested printing calls."
[& body]
`(let [baos# (ByteArrayOutputStream.)
ps# (PrintStream. baos#)]
(System/setErr ps#)
~#body
(System/setErr System/err)
(.close ps#)
(.toString baos#)))
See the docs here.
There are 5 variants (plus clojure.core/with-out-str):
with-err-str
with-system-out-str
with-system-err-str
discarding-system-out
discarding-system-err
Source code is here.

How to require keyword arguments in Common Lisp?

Given
(defun show-arg (a)
(format t "a is ~a~%" a))
(defun show-key (&key a)
(format t "a is ~a~%" a))
evaluating
(show-arg)
will lead to an error saying "invalid number of arguments: 0", where
(show-key)
will display a is NIL
How can I get SHOW-KEY to signal an error like SHOW-ARG does? Is there a way other than using (unless a (error "a is required")) in the function body? I am very fond of keyword arguments and use them constantly, and almost always want them to be required.
Keyword arguments are always optional, so you do need to manually check if they're given and signal an error if needed. It would be better to not require keyword arguments though. The compiler won't recognize them as required and thus won't given you an error message for missing arguments at compile time.
If you do want to require them, you can specify the arguments with a three element list; the first element being the argument, the second is the default value and the third is a variable that will be true if the argument was given. Checking the third element is better than checking the keyword itself, because then you can tell the difference between a NIL that was the default, and a NIL that the user gave as an argument.
(defun foo (&key (keyarg nil keyargp))
(unless keyargp (error "KEYARG is required."))
(* keyarg 2))
Edit
Now that I think about this a bit more, there actually is a way to get compile time errors for missing keyword arguments. Define a compiler macro for the function:
(defun foo (&key a b c d)
(* a b c d))
(define-compiler-macro foo (&whole whole &key (a nil ap) (b nil bp)
(c nil cp) (d nil dp))
(declare (ignore a b c d))
(unless (and ap bp cp dp)
(error "Missing arguments..."))
whole)
One possibility would be:
(defun foo (&key (arg1 (error "missing arg1 in call to function foo")))
arg1)
Using it:
CL-USER 80 > (foo)
Error: missing arg1 in call to function foo
1 (abort) Return to level 0.
2 Return to top loop level 0.
This will give an error at runtime, unfortunately not at compile time.

Testing if a Variable Contains a Function in Common Lisp

I am writing a common lisp program and I have a variable that can contain either a string or a function. I want to call the function if it is one and return that as well as the string. How do I test if a variable is a function?
Code so far:
(defun string-or-function (var)
(if (typep var 'simple-array)
var
(if "Function equivalent of typep goes here."
(setf temp (fn-that-does-something))
(string-or-function temp)
Edit: Code that works:
(defun string-or-function (var)
(let ((s-or-f (type-of var)))
(if (equal s-or-f 'function)
(print "function")
(if (equal (car s-or-f) 'simple-array)
(print "string")))))
Is there a better way to do it?
Common Lisp has a predicative type system. The notion that a value has a "principal" type doesn't make as much sense in Lisp. The type-of function is actually fairly infrequently used, as it makes less sense to ask "What is the type of X" and more sense to ask "Is X of type Y". This can be done with typep, or in your case more concisely with typecase, which is just a case statement for types.
(defun string-or-function (var)
(typecase var
(string (format t "string"))
(function (format t "function"))
(t (format t "something else"))))
I want to call the function if it is one and return that as well as the string.
I think you mean something like this:
(defun evaluate (arg)
"Returns something from evaluating ARG in some manner. If ARG is a string,
return it. If ARG is a function, call it with no arguments and return its
return value(s)."
(ctypecase arg
(string arg)
(function (funcall arg))))
If you need extensibility:
(defgeneric evaluate (arg)
(:documentation "Returns something from evaluating ARG in some manner."))
(defmethod evaluate ((arg string))
arg)
(defmethod evaluate ((arg function))
(funcall arg))
Here are some other ways:
(defun string-or-function-p (x)
(typep x '(or string function)))
...but you can probably also use check-type, which is not a predicate but a check which signals a restartable condition in case the value does not satisfy the type specification:
(check-type place (or string function))
If you happen to use this type a lot, define a custom type:
(deftype string-or-fun () '(or string function))
Of course, you can also use generic functions depending on your needs (silly example):
(defgeneric execute (object)
(:method ((s string)) (eval (read-from-string s)))
(:method ((f function)) (funcall f)))
But note that generic function dispatch on classes, not types, which are different things.
(eq (type-of var) 'function)
However, remember that Common Lisp keeps variables and function names in different namespaces, so (var 1 2 3) and (cons var 1) are looking in two different places. You probably cannot call var like (var), but will rather need to use (funcall var), depending on which namespace this is in.
Basically, you probably shouldn't be stuffing a function-or-maybe-a-string into one variable.

SBCL warning that a variable is defined but never used

I'm getting a warning from the sbcl compiler, that a variable has been defined but is not used. And the compiler is right. I want to get rid of the warning, but don't know how to do it. Here is an example:
(defun worker-1 (context p)
;; check context (make use of context argument)
(if context
(print p)))
(defun worker-2 (context p)
;; don't care about context
;; will throw a warning about unused argument
(print p))
;;
;; calls a given worker with context and p
;; doesn't know which arguments will be used by the
;; implementation of the called worker
(defun do-cmd (workerFn context p)
(funcall workerFn context p))
(defun main ()
(let ((context ()))
(do-cmd #'worker-1 context "A")
(do-cmd #'worker-2 context "A")))
The do-cmd-function expects worker-functions that implement a specific interface f(context p).
The sbcl compiler throws the following warning:
in: DEFUN WORKER-2
; (DEFUN WORKER-2 (CONTEXT P) (PRINT P))
;
; caught STYLE-WARNING:
; The variable CONTEXT is defined but never used.
;
; compilation unit finished
; caught 1 STYLE-WARNING condition
You need to declare that the parameter is intentionally ignored.
(defun worker-2 (context p)
(declare (ignore context))
(print p))
ignore will also signal a warning if you do use the variable. To suppress warnings in both cases, you can use the declaration ignorable, but this should only be used in macros and other such cases where it's not possible to determine whether the variable will be used at the point of its declaration.
In case you are not yet familiar with declare, note that it is not an operator, and instead can only appear in certain locations; in particular, it must be located before all forms in the defun body, though it can be either above or below a documentation string.

How is it possible to call a locally defined function from its symbol?

According to the CLHS, FUNCALL argument is a function designator, which can be a symbol denoting a function defined in the global environment. I am looking for a way to do this locally, like in this example:
(defun test ()
(let ((name 'local-function))
(flet ((local-function ()
'hello))
(funcall name))))
I am looking for a way to get the function definition from the local environment. Is it possible with Common Lisp?
If you're just trying to call a local function using funcall, note that a function designator can also be the function object, and you can get that by using the (function name) == #'name notation. I.e., you can do:
(defun test ()
(flet ((local-function ()
'hello))
(funcall #'local-function)))
You can return this value, too, and so let the local function “escape” outside. E.g., you could implement a counter:
(defun make-counter (init)
(flet ((counter ()
(incf init)))
#'counter))
; This case is simple, and could have been:
;
; (defun make-counter (init)
; (lambda ()
; (incf init)))
(let ((counter (make-counter 3)))
(list (funcall counter)
(funcall counter)
(funcall counter)))
;=> (4 5 6)
As uselpa pointed out though, you won't be able to get the function object via a symbol, much in the same way that there's no association at runtime between the symbol named "X" and the lexical variable x in
(let ((x 'foo))
x)
The lexical variables don't have any association at run time with the symbols that named them in the source code.
According to this, no. It doesn't work with eval either. I suppose that at run-time there is no trace left of the local function's name.
Also, my understanding is that if the function designator is a symbol, then symbol-function is used, which is not defined for local functions.

Resources