When is it appropriate to use keyword parameters vs optional? - function

Besides the cosmetic differences, what is the difference between key and optional these:
(defun play (&key now)
...)
(defun play (&optional now)
...)
As i understand it, in both cases:
they are optional
neither returns a list to the function like &rest

&optional
Optional arguments are, hmm, optional. You can omit them and they may have default values. They need to be provided in order.
(defun hello-world (&optional (message "Hi there!")
(stream *standard-output*))
(format stream "Hello World: ~a" message)
(finish-output stream))
(hello-world "Good morning!")
Above omits the output stream, since it is optional and has a default value.
(with-output-to-string (stream)
(hello-world "Good morning!" stream))
Above provides a stream, since we don't want to use the default value.
Thus the following three call variations are possible:
(hello-world "Good morning!" stream)
(hello-world "Good morning!")
(hello-world)
&key
Keyword arguments are named, optional and can be provided in any order:
(defun hello-world (&key (message "Hi there!")
(stream *standard-output*))
(format stream "Hello World: ~a" message)
(finish-output stream))
Now all the following five call variations are possible:
(hello-world :message "Good morning!" :stream stream)
(hello-world :stream stream :message "Good morning!")
(hello-world :message "Good morning!")
(hello-world :stream stream)
(hello-world)
One can provide the keyword/value pairs in any order, omit some or omit all.
Benefits of keyword arguments
Thus keyword arguments give a lot of flexibility:
the developer usually needs not to remember the exact order of arguments
the developer can provide all, a subset or none of the arguments
the code gets more self-documenting, since the parameters are named in the function call
The price to pay: keyword arguments may make some calls slower than calls with fixed parameter lists.
When to use keyword parameters?
Developers will write functions, macros, ... with keyword parameters when there are multiple (even many) optional arguments without clear order preference. The more readable code is an added advantages.

When you use optional parameters, you can only omit arguments at the end of the argument list, since they're processed in order. If there are several optional arguments and you want to be selective about which you want to provide, you normally use keyword arguments.
See the built-in functions that use keyword arguments for examples. OPEN has lots of options, but any particular call will generally only use a couple of them. If it used &optional and you wanted to provide the last optional argument, you would have to fill in all the preceding arguments with default values.

Related

Is the Macro argument a function?

I am trying to determine whether a given argument within a macro is a function, something like
(defmacro call-special? [a b]
(if (ifn? a)
`(~a ~b)
`(-> ~b ~a)))
So that the following two calls would both generate "Hello World"
(call-special #(println % " World") "Hello")
(call-special (println " World") "Hello")
However, I can't figure out how to convert "a" into something that ifn? can understand. Any help is appreciated.
You might want to ask yourself why you want to define call-special? in this way. It doesn't seem particularly useful and doesn't even save you any typing - do you really need a macro to do this?
Having said that, if you are determined to make it work then one option would be to look inside a and see if it is a function definition:
(defmacro call-special? [a b]
(if (#{'fn 'fn*} (first a))
`(~a ~b)
`(-> ~b ~a)))
This works because #() function literals are expanded into a form as follows:
(macroexpand `#(println % " World"))
=> (fn* [p1__2609__2610__auto__]
(clojure.core/println p1__2609__2610__auto__ " World"))
I still think this solution is rather ugly and prone to failure once you start doing more complicated things (e.g. using nested macros to generate your functions)
First, a couple of points:
Macros are simply functions that receive as input [literals, symbols, or collections of literals and symbols], and output [literals, symbols, or collections of literals and symbols]. Arguments are never functions, so you could never directly check the function the symbol maps to.
(call-special #(println % " World") "Hello") contains reader macro code. Since reader macros are executed before regular macros, you should expand this before doing any more analysis. Do this by applying (read-string "(call-special #(println % \" World\") \"Hello\")") which becomes (call-special (fn* [p1__417#] (println p1__417# "world")) "Hello").
While generally speaking, it's not obvious when you would want to use something when you should probably use alternative methods, here's how I would approach it.
You'll need to call macroexpand-all on a. If the code eventually becomes a (fn*) form, then it is guaranteed to be a function. Then you can safely emit (~a ~b). If it macroexpands to eventually be a symbol, you can also emit (~a ~b). If the symbol wasn't a function, then an error would throw at runtime. Lastly, if it macroexpands into a list (a function call or special form call), like (println ...), then you can emit code that uses the thread macro ->.
You can also cover the cases such as when the form macroexpands into a data structure, but you haven't specified the desired behavior.
a in your macro is just a clojure list data structure (it is not a function yet). So basically you need to check whether the data structure a will result is a function or not when it is evaluated, which can be done like show below:
(defmacro call-special? [a b]
(if (or (= (first a) 'fn) (= (first a) 'fn*))
`(~a ~b)
`(-> ~b ~a)))
By checking whether the first element of the a is symbol fn* or fn
which is used to create functions.
This macro will only work for 2 cases: either you pass it a anonymous function or an expression.

The function is undefined. (recursion)

I am writing a simple member function that returns the value associated with that member. The first line of the conditional (to test if the first value is the one we're looking for) works fine, but the recursive part (to test parts of the list that are further along) returns an error every time.
Here is my function:
(defun mem (prop L)
(cond
((eq (caar L) prop) (print cadar L)))
(t (mem (prop (cdr L)))))) // error is on this line!
So, if I enter
(mem `i `((i 1) (j 2)))
it correctly returns 1. However, if I enter
(mem `j `((i 1) (j 2)))
it returns an error that "function prop is undefined."
How do I let the program know that prop isn't a function, but is just an input parameter?
This is my first lisp program, so I'm assuming the answer is incredibly simple, but I have tried many things and have yet to succeed.
The problem in particular is the snippet: (prop (cdr L)). This tries to call prop, passing it (cdr L). To pass it as an argument to mem, simply leave out the extra parentheses: (mem prop (cdr L)).
If you're having a problem figuring out where to put parentheses in general, note that Lisp syntax is very similar to mathematical syntax for functions, except the function goes on the inside of the parentheses (and you use spaces instead of commas, but that isn't a problem here). For example, written in mathematical notation, you have: mem(prop(cdr(L))), instead of mem(prop, cdr(L)).
Other Issues
It looks like you have an extra parentheses after the first branch of the cond, which ends it early. Use an editor/IDE with parentheses matching to catch this sort of error. Emacs does it, as does DrRacket. The former can be used with Common LISP via SLIME (search the web for set-up instructions for your platform), while the latter readily supports Scheme.
The semicolon (";") is the comment character used in most LISPs.
print isn't necessary for this function, and (depending on its behavior) may be incorrect. In some LISPs (e.g. Common LISP), it returns its argument, but in others it may return nil or the instance of some void type.
Quasiquote (aka backquote, backtick) is also unnecessary. Quasiquote lets you quote some symbols, while others (those prefixed with a comma) are replaced with their values. Since you don't need substitution in the quoted expressions, a plain quote will work: (mem 'j '((i 1) (j 2))).
For readability, insert more whitespace between closing and opening parentheses.

Interactive "r" elisp defun with additional args?

Is it possible to write an interactive defun with code "r" that has an additional optional argument (so that it does things within the selected region, but with another argument)? I would like something like the following:
(defun my-function (start end &optional arg)
"Do something with selected region"
(interactive "r")
(if arg
(setq val arg)
(setq val 2))
(do things...))
Looking at the documentation it says
'r': Point and the mark, as two numeric
arguments, smallest first. This is the
only code letter that specifies two
successive arguments rather than one.
No I/O.
I'm not sure if the 'No I/O' and 'two successive arguments' means that it takes 2 and only 2 arguments (i.e., limited to the region's start and end point as args). Although it allows me to evaluate and run the defun with an additional argument, Emacs appears to be ignoring it.
Thank you.
To make interactive ask for multiple parameters, separate them with a newline character. For instance, if you want your third parameter be bound to the value of the prefix argument, define your function like this:
(defun my-function (start end &optional arg)
"Do something with selected region"
(interactive "r\np")
(if arg
(setq val arg)
(setq val 2))
(do things...))
M-x describe-function interactive gives you further information.
A function can be called in two ways:
Interactively: This is what happens when a user calls the command, e.g. when it has been bound to a key.
From lisp: When the function is called from another lisp function. e.g. (r 100 200 t).
In your case, you have to make sure that the arguments match the interactive specification, in this case it must accept two arguments. The third will not be used when called interactively (so then it will get the value nil).
NO I/O means that it will not prompt the user for input (like it does when it asks for a file name).
If you want your function to act differently depending in when the region is active, you could ask the function (use-region-p).

what is the parameter to ns?

what is the parameter to ns ? the documentation says something, but it's not clear (to me, at least)
my-new-namespace=> (doc ns)
-------------------------
clojure.core/ns
([name docstring? attr-map? references*])
Macro
Sets *ns* to the namespace named by name (unevaluated), creating it
if needed.
...the rest of the documentation was not copied
the confusion comes from all the other functions that play with namespaces:
user=> (find-ns 'my-new-namespace)
nil
user=> (remove-ns 'my-new-namespace)
nil
user=> (create-ns 'my-new-namespace)
#<Namespace my-new-namespace>
user=> (ns 'my-new-namespace)
java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol (NO_SOURCE_FILE:26)
user=> (ns my-new-namespace)
nil
my-new-namespace=>
find-ns, create-ns, remove-ns take my-new-namespace quoted, while ns takes my-new-namespace unquoted
so, what is the deal ? why some get a quoted form and others get and unquoted form of my-new-namespace ?
what is, in each case, my-new-namespace ?
ps: think i figured out the answer to this as i was writing the question here, but it seemed and interesting exercise, so the question still got posted :D
ns is a macro and under the hood if quotes the name to save you the trouble:
user> (macroexpand '(ns foo))
(do (clojure.core/in-ns (quote foo)) (clojure.core/with-loading-context
(clojure.core/refer (quote clojure.core))))
the other functions cant get away with unquoted arguments because they are functions, and functions have there arguments evaluated first.
the ns macro, as a macro, gets to look at and twiddle its arguments before they are evaluated so it can get at the my-new-namespace before the reader attempts to look it up as a variable name.
in short this saves wear and tare on your keyboard and wrists ;) Just kidding, the in both cases what the function receives is a symbol they just differ in what you have to do to pass them that symbol.
for comparason; if you where to go ahead and pass (ns 'my-new-namespace) it would get the symbol 'my-new-namespace quote and all! you likely don't want the quote to be part of the name space.
if you want to make it consistent you could write wrapper macros that take unquoted symbols for the rest of the namespace functions that simply quote the first argument and return a call to the real function (remember that macros return the code to be called)
(defmacro my-find-ns [name]
`(find-ns (quote ~name)))
though this would break "the first rule of macro club"
the error about the argument being a list is caused by it attempting to use (quote my-new-namespace) as a name
user> (macroexpand '(ns 'foo))
(do (clojure.core/in-ns (quote (quote foo))) (clojure.core/with-loading-context
(clojure.core/refer (quote clojure.core))))

can if be a proper function rather than a special form

I finally started learning functional languages (emacs lisp) and it makes explicit distinction between functions and special forms such as flow control , for example if.
Is there a fundamental/theoretical reason why special forms are distinct from functions? do any languages provide functional if?
Thanks
With eager evaluation the distinction is required, languages with lazy evaluation (i.e. Haskell) if et al. can be functions.
Eager evaluation: The function's arguments are evaluated before calling the function, and only the results are passed to the function.
Lazy evaluation: A function's arguments evaluated if and only if they are accessed.
If if was a normal function, then both its arguments—the then form and the else form—would both be evaluated before calling the if function, because that's the rule of function evaluation: evaluate all arguments to produce values, then provide that sequence of values as arguments to the function designated by the first symbol in the list.
Instead, with if what you want to do is evaluate exactly one of the then form and else form, not both. In order to suppress evaluation of one or the other, you need either a macro or a special form.
In languages like Emacs Lisp and Common Lisp, special forms are built-in language constructs. They have different evaluation rules that normal function calls. For normal function calls all arguments are evaluated. So, you can't write an IF as a normal function - the condition determines which clause gets evaluated. Also usually you can't write your own special forms - in Common Lisp there is no language construct for defining a special form (though individual implementations must have implemented the existing ones somehow. This leads to macros. With macros you can write a syntactic transformation that transforms one expression into another one. To be able to write IF as a macro, you need to have another conditional form, which you can use for the transformed code. Lisp provides conditionals as basic constructs. Let's assume COND is such a basic construct, then you could expand IF into a usage of COND.
MY-IF as a macro in Common Lisp:
(defmacro my-if (condition true-clause false-clause)
`(cond (,condition ,true-clause)
(t ,false-clause)))
So
(my-if (foo-p) 'one 'two)
gets expanded into
(cond ((foo-p) 'one)
(t 'two))
For completeness: there are no special forms in the Pico language for example, and if is a primitive function while Pico is inspired by Scheme and has eager evaluation by default.
In Scheme you could write
(define (true t f)
(t))
(define (false t f)
(f))
(define (function_if c t e)
(c t e))
and then
(function_if true (lambda () 'true) (lambda () 'false))
==> true
What makes this manageable in Pico is that you can define functional parameters that take functional arguments that are "automatically" delayed. This means that you don't have to do the wrapping inside lambdas yourself. Pico therefore has eager evaluation but with lazy evaluation on demand, bypassing the need for special forms.
So, in Scheme syntax with functional parameters you can encode booleans as:
(define (true (t) (f))
(t))
(define (false (t) (f))
(f))
Then function if becomes:
(define (function_if c (t) (e))
(c (t) (e)))
and
(function_if true 'true 'false)
==> true
As another example, the definition of the function and is (define (and p (q)) (p (q) false)).
Similarly you can define or, not, while, for, ... as functions, using the above encoding of booleans.
Short answer: No.
Long(er) answer: (if ...) requires that you control the evaluation order of the arguments. Lisp, being an eager language cannot do this in a function.
Workaround: do it in a macro:
(defmacro _if (cnd true false)
(let ( (gcond (gensym))
(gresp (gensym)))
`(let ( (,gcond ,cnd) ;`#quotes
(,gresp nil))
(and ,gcond (setf ,gresp (multiple-value-list ,true)))
(and (not ,gcond) (setf ,gresp (multiple-value-list ,false)))
(values-list ,gresp))))
For example:
[dsm#localhost:~]$ clisp -q
[1]> (defmacro _if (cnd true false)
(let ( (gcond (gensym))
(gresp (gensym)))
`(let ( (,gcond ,cnd) ;`#quotes
(,gresp nil))
(and ,gcond (setf ,gresp (multiple-value-list ,true)))
(and (not ,gcond) (setf ,gresp (multiple-value-list ,false)))
(values-list ,gresp))))
_IF
[2]> (_if (= 1 1) (+ 2 3) "bar")
5
[3]> (_if (= 1 2) (+ 2 3) "bar")
"bar"
[4]>
In Scala it's possible to model if with correct side-effect evaluation using call-by-name arguments.
def If[A](cond : Boolean, truePart : => A, falsePart : => A) = if (cond) truePart else falsePart
These feature can be used to model lots of new control structures as well.
IF could be a function in a functional language having call-by-name semantics (lazy evaluation), as in Lambda Calculus or Algol. In fact that is, I think, at the heart of the relationship between Turing Machines and Lambda Calculus as equivalent foundations for computing. However, in languages having side-effects (like assignments to variables) it is not much use, because when things happen is important.