I am having some trouble in how to define no operation in scheme language
like ; in c
i want to do something like this:
(cond
[(null? exp) nop ]
.....
)
if i leave it empty it wiil return #t
thanks!
Note that functional programs are different to imperative programs. You should always think in every expression/function to return something (the result or value of that expression). With conditionals, you have to be careful to maintain this "something" through all the different branches, as your expression has to yield a value in any case.
Then, you have to decide what you want to return in that case, and build the code accordingly. If you don't want to return #t, you can return just #f or the empty list:
(cond
[(null? exp) #f]
.....
)
In fact, if you think carefuly, the concept of a "no op" (that is, do nothing), in C, is almost the same than "producing some value", because you're doing nothing apart from producing the value, that doesn't induce any change at all in your program.
Scheme has no statements, only expressions. Each expression returns a value -or may never return-
So you want an expression which does not compute much. You could use nil (or #f, or any other value) for that purpose:
(cond
((null? exp) ())
....
)
If you wrote a condition with only a test - and no "then" body sub-expressions
(cond
((null? exp))
)
then the result of the cond when exp is nil is the result of the (null? exp) test which is #t
actually, when exp is null, you could just return exp itself.
You should probably change your program to eliminate useless condition. But if you just need a nil value, the standard answer is to say (if #f #f), which is a one-legged if that is always false but has no false expression, hence returns nothing.
Related
Why does the following Clojure program throw a NullPointerException?
user=> (defn x []
"Do two things if the expression is true."
(if true ((println "first expr") (println "second expr")) false))
user=> (x)
first expr
java.lang.NullPointerException (NO_SOURCE_FILE:0)
second expr
This is a simplified version of my actual use case, where I want to execute maybe three statements (pull values from the DB) before returning a map - {:status 200, :body "Hello World"} inside of the branch.
It is trying to treat the result of the first println as a function to call on the second println function.
You need a do.
(defn x []
"Do two things if the expression is true."
(if true (do (println "first expr") (println "second expr")) false))
(x)
The do special form (progn in CL, begin in Scheme) executes each of its arguments in sequence and returns the result of the last one.
If nil is ok as a return value in the else case, consider using when which has an implicit do block:
(defn x []
"Do two things if the expression is true."
(when true
(println "first expr")
(println "second expr")))
Not that it matters in your particular case, but do know the difference between (do ...) which will load each form in its own classloader, and an empty let form (let [] ...) which evaluates the whole form in a single classloader.
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.
I am trying to declare a local variable for use within a recursive function, but my let seems to be being called each time the function recurses. I want the let function to be called once to declare a variable and give it the value nil, I'd then like to update the value of this local variable within my recursive function without it being wiped with each recurse.
Here is a simplified framework of my code.
(defun recursive-function (l1 l2)
(let ((?x nil))
(cond (...
...
... ;trying to update value of ?x here with (setf ?x 5)
(recursive-funtion (rest l1)(restl2)) ;recursive call made
))))
What you've written is exactly what you've said you don't want; a local variable inside of the recursive function that should be updating it with each pass. If I've understood you correctly, you'll need to do something like
(defun recursive-function (l1 l2)
(let ((?x nil))
(labels ((actual-recursion (a b)
(cond (...
...
...
(actual-recursion (rest a) (rest b))))))
(actual-recursion l1 l2))))
so that each recursive call doesn't create a new binding of ?x.
I am curious how
(write
(make-instance 'simple-error
:format-control "A:~a ~% B:~a~%"
:format-arguments `("A" "B"))
:stream nil)
works, as I tried to implement it myself to gain experience in basic lisp funcionality but soon had to realize, that I am not able to. As the intuitive way of implementation:
(defmethod my-write ((simple-error err))
(FORMAT nil (if (simple-condition-format-control err)
(simple-condition-format-control err)
"")
(simple-condition-format-arguments err)))
obviously cannot work, as (simple-condition-format-arguments err) returns the list of arguments and therefore, in the example above, "B:~a" does not have a corresponding parameter to print.
So how would I actually implement this method?
You can use apply for this. It takes the function passed as its first argument and applies it to arguments constructed from its other arguments. For example, (apply #'f 1 2) calls (f 1 2), (apply #'f 1 '(2 3)) calls (f 1 2 3) and so on. It's perfectly suited for this situation.
SBCL has a function almost identical to yours:
(defun simple-condition-printer (condition stream)
(let ((control (simple-condition-format-control condition)))
(if control
(apply #'format stream
control
(simple-condition-format-arguments condition))
(error "No format-control for ~S" condition))))
As mentioned by Samuel, you need to use APPLY.
Also note that NIL for the stream in WRITE does something else than in FORMAT. With FORMAT the stream argument NIL causes the output to be returned as a string. With man other output functions, like WRITE, it means standard output.
I'm teaching myself Clojure.
In a non-FP language, I could easily enough write nested if's, and if I didn't specifically put an else, then control would just flow out of the if block. For example:
Thing myfunc()
{
if(cond1)
{
if(cond2)
return something;
}
return somethingelse;
}
However, in Clojure, there's no return statement (that I know of), so if I write:
(defn myfunc []
(if (cond1)
(if (cond2) something))
somethingelse)
then there's no "return" on "something". It seems to just kind of say, ok, here we have a value, now let's keep on executing. The obvious solution would be to combine the conditions, i.e.:
(if (and (cond1) (cond2))
something
somethingelse)
but this gets unwieldy/ugly for large conditions. Also, it would take additional finagling to add a statement to the "else" part of cond1. Is there any kind of elegant solution to this?
This is the subtle difference between imperative and functional approach. With imperative, you can place return in any place of the function, while with functional the best way is to have clear and explicit exeecution paths. Some people (me including) prefer the latter approach in imperative programming as well, recognizing it as more obvious and manageable and less error-prone.
To make this function explicit:
Thing myfunc() {
if(cond1) {
if(cond2)
return something;
}
return somethingelse;
}
You can refactor it to:
Thing myfunc() {
if(cond1 && cond2) {
return something;
} else {
return somethingelse;
}
}
In Clojure, its equivalent is:
(defn myfunc []
(if (and cond1 cond2)
something
somethingelse))
If you need an "else", your Java version could become:
Thing myfunc() {
if(cond1) {
if(cond2) {
return something;
} else {
return newelse;
}
} else {
return somethingelse;
}
}
... and its Clojure equivalent:
(defn myfunc []
(if cond1
(if cond2 something newelse)
somethingelse))
(if (and (cond1) (cond2))
something
somethingelse)
(cond
(and (cond1) (cond2)) something
:else somethingelse)
cond does do this if you want to compare the same thing; in a switch-case you can use condp.
I don't see that kind of code very often, but that's the way to do it.
Imperative Languages have if-statements that say if this then do that else do that and functional languages have if-expressions that say if this return that else return this. it's a different way of looking at the same idea, that reflects a very different approach to expressing problems. in Functional languages everything has a value, really everything, even if you don't do anything with that value.
When i was making the transition it helped a lot to ask my self "what result should this function return" instead of the question "what should this function do" that i was accustomed to asking.
There is no explicit return statement in Clojure, but your code will "return" on "something" because you don't have any expressions after that if and in Clojure the result of the last expression is used as the function’s return value.
The (imho) most readable approach to solve this problem is provided by the core.match library.
This code snippet:
(defn myfunc []
(if (cond1)
(if (cond2) something))
somethingelse)
becomes:
(ns my.project
(:require [clojure.core.match :refer [match]]))
(defn myfunc []
(match [cond1 cond2]
[true true] something
[_ _] somethingelse))
Note that you can match on other values than boolean values, like matching on keywords (or any clojure value for that matter), e.g.:
(defn myfunc []
(match [cond1 some-kw another-kw]
[true :a :z] foo
[true :b _] gee
[true _ _] bar
[false _ _] giz
[_ _ _] default))
More examples.
You could also use the (cond) macro:
(defn length-checker [a b]
(cond
(= 3 (count (str a))) (if (= 3 (count (str b)))
(println "both numbers are 3 digits long")
(println "first number is 3 digits, but the 2nd not!"))
:else (println "first- or both of the numbers are not 3 digits")))