Conditionally choosing which function to call - functional-programming

Why doesn't the following work?
((if t + -) 1 1)
How can I get the if expression to resolve to provide the correct function? I don't want to repeat myself, as in (if t (+ 1 1) (- 1 1)).

Emacs Lisp is a Lisp-2, meaning it has a separate namespace for functions. To refer to a function as a value in Emacs Lisp, you need to quote it. And to call a function referenced in this way, you need to use funcall. So what you want is:
(funcall (if t '+ '-) 1 1)

Related

Lisp case with different equality predicate

As a part of a Tic Tac Toe playing bot, I need a function that evaluates combinations of tiles to points. The code would look something like this:
(case combination
("EEEEE" 0)
("EEEEP" 1)
("EEEPE" 1)
("EEEPP" 2)
("EEPEE" 1)
("EEPEP" 2)
("EEPPE" 2)
("EEPPP" 3)
("EPEEE" 1)
("EPEEP" 2)
("EPEPE" 2)
("EPEPP" 3)
("EPPEE" 2)
("EPPEP" 3)
("EPPPE" 3)
("EPPPP" 4)
("PEEEE" 1)
("PEEEP" 2)
("PEEPE" 2)
("PEEPP" 3)
("PEPEE" 2)
("PEPEP" 3)
("PEPPE" 3)
("PEPPP" 4)
("PPEEE" 2)
("PPEEP" 3)
("PPEPE" 3)
("PPEPP" 4)
("PPPEE" 3)
("PPPEP" 4)
("PPPPE" 4)
("PPPPP" 5))
(This is not the place to discuss the value of such an approach, for it is used for reasons unrelated to the question)
The problem is that case uses a predicate that doesn't return true for identical strings that aren't the same object (hard to find if it's eq or eql). How can you change that?
EDIT: I solved the original problem by converting the string into a corresponding binary number, which can be compared using eql or used as an index in a list.
Use alexandria:switch from the alexandria library, available from quicklisp.
(switch (combination :test #'string=)
("FOO" …)
…)
Your code just calculates (count #\P combination).
Usually I would convert the string in a number and compute with it. Using LOGCOUNT to get the on bits or something. Even if I were using a large CASE-like switch, I would convert the string once to a number, instead of doing a multitude of string comparisons.
You could write a macro:
(defmacro string-case (key &rest forms)
(let ((k (gensym "KEY")))
`(let ((,k ,key))
(cond
,#(loop for (str . body) in forms
collect `((string= ,k ,str) ,#body))))))
And then use it like case. Note that this macro will check each substring one at a time (up to 32 branches in your case), which is less efficient than eg looking at the first character and deciding what to do, then looking at the next character and so on (5-10 branches in your case), which is less efficient than doing what you actually intend (eg counting #\P) (this can be done with 5-6 easily predicted branches, or maybe 10 depending on implementation). Of these options, the second generated the most code, then the first, then the third.
Another approach would be to convert combination to a symbol. The resulting code will look like this:
(case (intern combination)
(EEEEE 0)
(EEEEP 1)
(EEEPE 1)
...)
But you need to keep in mind that intern operates at runtime in the context of current package (*package*), which means that if this is part of a function that is called outside of the package where it's defined, it will not work. There are 2 ways to work around this (basically, two variations of one): either intern in the package ((intern combination <your-package>)) or intern as keyword. In the later case, the whole form will look like this:
(case (intern combination :keyword)
(:EEEEE 0)
(:EEEEP 1)
(:EEEPE 1)
...)
Also worth noting may be performance considerations. They shouldn't be a problem as, although interning is a rather heavy operation, initially, when it's called repeatedly on an already interned symbol it's, basically, just a dictionary lookup.
Another solution may be to define the rules as a list, and search through the list for the matching string.
(defun match-combination (combination)
(let ((rules '(("EEEEE" 0)
("EEEEP" 1)
("EEEPE" 1)
...)))
(cadr (find combination rules :key #'car :test #'string=))))

Recursive Loop in Clojure via Macro is throwing me errors

I've been trying to write a recursive loop in clojure that will print me out the very last number in the list. The point is not that I need to get the last number (for which I'm sure there's a built in function for that) but that I want to better understand recursion and macros in clojure. So I have this macro...
(defmacro loop-do [the-list]
`(if (= (count '~the-list) 1)
(println (first '~the-list))
(loop-do (rest '~the-list))))
But I get a stackoverflow error. What am I doing wrong?
How will people use your macro?
Somewhere, someone will call:
(loop-do list)
As a piece of code, those are only two symbols in a list. The first one is recognized as your macro, and the second one, list, is a symbol that represents a variable that will be bound at runtime. But your macro only knows that this is a symbol.
The same goes for:
(loop-do (compute-something))
The argument is a form, but you do not want to get the last element of that form, only the last element of the list obtained after evaluating the code.
So: you only know that in your macro, the-list will be bound to an expression that, at runtime, will have to be a list. You cannot use the-list as-if it was a list itself: neither (count 'list) nor (count '(compute-something)) does what you want.
You could expand into (count list) or (count (compute-something)), though, but the result would only be computed at runtime. The job of the macro is only to produce code.
Recursive macros
Macros are not recursive: they expand into recursive calls.
(and a b c)
might expand as:
(let [a0 a] (if a0 a0 (and b c)))
The macroexpansion process is a fixpoint that should terminate, but the macro does not call itself (what would that mean, would you expand the code while defining the macro?). A macro that is "recursive" as-in "expands into recursive invocations" should have a base case where it does not expand into itself (independently of what will, or will not, happen at runtime).
(loop-do x)
... will be replaced by:
(loop-do (rest 'x))
... and that will be expanded again.
That's why the comments say the size actually grows, and that's why you have a stackoverflow error: macroexpansion never finds a fixpoint.
Debugging macros
You have a stackoverflow error. How do you debug that?
Use macroexpand-1, which only performs one pass of macroexpansion:
(macroexpand-1 '(loop-do x))
=> (if (clojure.core/= (clojure.core/count (quote x)) 1)
(clojure.core/println (clojure.core/first (quote x)))
(user/loop-do (clojure.core/rest (quote x))))
You can see that the generated code still contains a call to usr/loop-do , but that the argument is (clojure.core/rest (quote x)). That's the symptom you should be looking for.

Unbound variable in edwin scheme

I'm learning Scheme for the first time, and for practice I'm trying to write a program that returns a list of a specified length with all values equal to 1. I'm using the MIT/GNU Edwin editor on Windows 10. Here's the code I typed:
(define (listlength n)
(if (= n 1)
(list 1)
(append (list 1) (listlength (- n 1)))))
(listlength 5)
I would hope for C-x C-e to return (1 1 1 1 1), but instead I get an unbound variable error:
;Unbound variable: listlength
;To continue, call RESTART with an option number:
; (RESTART 3) => Specify a value to use instead of listlength.
; (RESTART 2) => Define listlength to a given value.
; (RESTART 1) => Return to read-eval-print level 1.
;Start debugger? (y or n):
The only reason I can think of is that it doesn't like me calling listlength in the definition of listlength, but that's supposed to be part of what makes Scheme Scheme, so??? i'm at a loss?? Thanks for any help you can give me!
You should check if you use C-x C-e at the end of the function. C-x C-e will evaluate the expression at the left of the cursor. Or you can use M-z ,which will evaluate the whole expression not matter where is the cursor.
I am also a beginner of Scheme, and I hope the answer can help you!

STEP macro does not work in Clozure CL

I want to use a step function to see how it went to the expected output, but it's not working.
Like this simple example:
(STEP (IF (ODDP 3) 'YES 'NO))
but nothing happens.
Is there any optimization that makes me can't see the trace steps ???
How to turn it off?
Thanks!
It's because CL:STEP is not implemented on CCL that I implemented com.informatimago.common-lisp.lisp.stepper.
You can get it with quicklisp.
The documentation is at: https://gitorious.org/com-informatimago/com-informatimago/source/2b53ae44e8fa4d040fafcf4d93976500a8e464dc:common-lisp/lisp/stepper-packages.lisp#L146
STEP is not supported in CCL.
Solution for TRACE:
When a (globally named) function FOO is defined with DEFUN, the compiler is allowed to assume that functional references to that function name refer to the function being defined (unless they're lexically shadowed); it can therefore skip the implicit SYMBOL-FUNCTION ("call whatever is in the function cell of FOO") on a self-call (a call to FOO from within FOO.) This saves an instruction or two on those calls, but (since TRACE works by changing what SYMBOL-FUNCTION returns) those inlined self-calls can't be traced.
However, the compiler can't do this (can't even assume that something defined by DEFUN won't be redefined later) if the function name is declared NOTINLINE at the point of the self call:
example:
? (defun fact (x acc)
(declare (notinline fact))
(if (= x 0)
acc
(fact (- x 1) (* x acc))))
? (trace fact)
NIL
? (fact 3 1)
0> Calling (FACT 3 1)
1> Calling (FACT 2 3)
2> Calling (FACT 1 6)
3> Calling (FACT 0 6)
<3 FACT returned 6
<2 FACT returned 6
<1 FACT returned 6
<0 FACT returned 6
? (step (fact 3 1))
0> Calling (FACT 3 1)
1> Calling (FACT 2 3)
2> Calling (FACT 1 6)
3> Calling (FACT 0 6)
<3 FACT returned 6
<2 FACT returned 6
<1 FACT returned 6
<0 FACT returned 6
That's the way to say to the compiler, "as a matter of policy, I'd rather have the ability to trace functions which call themselves and are defined with DEFUN and don't care about saving a few cycles per self-call".
from: DebugWithOpenMCL
or Evaluate the following form:
(DECLAIM (OPTIMIZE (DEBUG 3)))
before defining any function to be traced.
I don't think Clozure CL supports stepping. IIRC nobody has funded this feature yet. It would need some work, since Clozure CL lacks an interpreter (where stepping could be supported relatively painless).
Other implementations support stepping.
This library is not distributed on quicklisp anymore however it builds successfully when installed as a local quicklisp project.
use cl-stepper:step instead of cl-user:step , 'cause Clozure CL don't support it.
if you have already installed quicklisp, try to install it : like this.
(ql:quickload "com.informatimago.common-lisp.lisp.stepper")
(defpackage :test (:use :cl-stepper))
(in-package :test)
(def bar (hoge)
;; define some function
)
(step (bar 3))

How to call particular function depending on variable that's passed in?

I'm fairly new to lisp but I've been playing around with it. I have several problems which I need clarifying. Below is my little macro that I defined.
(defmacro transform (query)
'(lambda (row)
(eq (nth 1 query) (nth 0 (nth 0 row)))
)
)
I'm just wondering how I can specify the function to use in the body dynamically? Say if I want to use the "+" or "-" function instead of "eq", or even another function that I defined? Like I thought it'd be possible to pass in the name of the function as a parameter but that obviously doesn't work. I also get variable unbound errors when I modify the list (query) that's passed in.
In the body of the macro, you can use all of Lisp's run-time library to generate the actual expansion. So, for example:
(defmacro transform (query &key (test 'eq))
(let ((row-var (gensym)))
`(lambda (,row-var)
(,test (nth 1 ,query) (nth 0 (nth 0 ,row-var))))))
This version uses the "backtick" instead of a plain apostrophe, which allows for "unquoting" of forms within the body, thus allowing the inclusion of generated forms into the result.
You can use this macro like your original version:
(transform (...))
or (passing an explicit test function):
(transform (...) :test equal)
Note, that you should not use plain symbols as variable names in macro expansions (as your row argument to the generated lambda expression) as that might accidentally interfer with the use of that symbol at the site of the use of your macro. You simply don't know when writing your macro, whether there will be a variable called row somewhere when your macro is used, and whether it is not already used within the query form/expression. Your original definition would "capture" the variable, possibly altering the meaning of whatever query does.
funcall is the answer! Decided to just pass it in and use funcall to evaluate the function.

Resources