I'm attempting to implement my own Clojure 'or' macro (called 'my-or'). So far I've got:
(defmacro my-or
[& args]
(let [[x xs] (seq args)]
`(if ~x ~x (my-or ~xs))))
However, when calling this function, for example:
(my-or false 4 3)
this causes a StackOverflowError. I appreciate what I've written is recursive, but what exactly is it about the function that causes the error? Incidentally, I've also taken a look at the official implementation of 'or' in the clojure.core library, so I'm aware of a solution that works.
(Maybe tail-recursion is relevant here? Not sure.)
Thanks
Daniel
You doesn't have the base case of recursion i.e case where recursion stops:
(defmacro my-or
[& args]
(let [[x & xs] args]
(if (nil? xs) `(if ~x ~x)
`(if ~x ~x (my-or ~#xs)))))
Related
I'm studying lambda calculus with the book "An Introduction to Functional Programming Through Lambda Calculus" by Greg Michaelson.
I implement examples in Clojure using only a subset of the language. I only allow :
symbols
one-arg lambda functions
function application
var definition for convenience.
So far I have those functions working :
(def identity (fn [x] x))
(def self-application (fn [s] (s s)))
(def select-first (fn [first] (fn [second] first)))
(def select-second (fn [first] (fn [second] second)))
(def make-pair (fn [first] (fn [second] (fn [func] ((func first) second))))) ;; def make-pair = λfirst.λsecond.λfunc.((func first) second)
(def cond make-pair)
(def True select-first)
(def False select-second)
(def zero identity)
(def succ (fn [n-1] (fn [s] ((s False) n-1))))
(def one (succ zero))
(def zero? (fn [n] (n select-first)))
(def pred (fn [n] (((zero? n) zero) (n select-second))))
But now I am stuck on recursive functions. More precisely on the implementation of add. The first attempt mentioned in the book is this one :
(def add-1
(fn [a]
(fn [b]
(((cond a) ((add-1 (succ a)) (pred b))) (zero? b)))))
((add zero) zero)
Lambda calculus rules of reduction force to replace the inner call to add-1 with the actual definition that contains the definition itself... endlessly.
In Clojure, wich is an application order language, add-1 is also elvaluated eagerly before any execution of any kind, and we got a StackOverflowError.
After some fumblings, the book propose a contraption that is used to avoid the infinite replacements of the previous example.
(def add2 (fn [f]
(fn [a]
(fn [b]
(((zero? b) a) (((f f) (succ a)) (pred b)))))))
(def add (add2 add2))
The definition of add expands to
(def add (fn [a]
(fn [b]
(((zero? b) a) (((add2 add2) (succ a)) (pred b))))))
Which is totally fine until we try it! This is what Clojure will do (referential transparency) :
((add zero) zero)
;; ~=>
(((zero? zero) zero) (((add2 add2) (succ zero)) (pred zero)))
;; ~=>
((select-first zero) (((add2 add2) (succ zero)) (pred zero)))
;; ~=>
((fn [second] zero) ((add (succ zero)) (pred zero)))
On the last line (fn [second] zero) is a lambda that expects one argument when applied. Here the argument is ((add (succ zero)) (pred zero)).
Clojure is an "applicative order" language so the argument is evaluated before function application, even if in that case the argument won't be used at all. Here we recur in add that will recur in add... until the stack blows up.
In a language like Haskell I think that would be fine because it's lazy (normal order), but I'm using Clojure.
After that, the book go in length presenting the tasty Y-combinator that avoid the boilerplate but I came to the same gruesome conclusion.
EDIT
As #amalloy suggests, I defined the Z combinator :
(def YC (fn [f] ((fn [x] (f (fn [z] ((x x) z)))) (fn [x] (f (fn [z] ((x x) z)))))))
I defined add2 like this :
(def add2 (fn [f]
(fn [a]
(fn [b]
(((zero? b) a) ((f (succ a)) (pred b)))))))
And I used it like this :
(((YC add2) zero) zero)
But I still get a StackOverflow.
I tried to expand the function "by hand" but after 5 rounds of beta reduction, it looks like it expands infinitely in a forest of parens.
So what is the trick to make Clojure "normal order" and not "applicative order" without macros. Is it even possible ? Is it even the solution to my question ?
This question is very close to this one : How to implement iteration of lambda calculus using scheme lisp? . Except that mine is about Clojure and not necessarily about Y-Combinator.
For strict languages, you need the Z combinator instead of the Y combinator. It's the same basic idea but replacing (x x) with (fn [v] (x x) v) so that the self-reference is wrapped in a lambda, meaning it is only evaluated if needed.
You also need to fix your definition of booleans in order to make them work in a strict language: you can't just pass it the two values you care about and select between them. Instead, you pass it thunks for computing the two values you care about, and call the appropriate function with a dummy argument. That is, just as you fix the Y combinator by eta-expanding the recursive call, you fix booleans by eta-expanding the two branches of the if and eta-reduce the boolean itself (I'm not 100% sure that eta-reducing is the right term here).
(def add2 (fn [f]
(fn [a]
(fn [b]
((((zero? b) (fn [_] a)) (fn [_] ((f (succ a)) (pred b)))) b)))))
Note that both branches of the if are now wrapped with (fn [_] ...), and the if itself is wrapped with (... b), where b is a value I chose arbitrarily to pass in; you could pass zero instead, or anything at all.
The problem I'm seeing is that you have too strong of a coupling between your Clojure program and your Lambda Calculus program
you're using Clojure lambdas to represent LC lambdas
you're using Clojure variables/definitions to represent LC variables/definitions
you're using Clojure's application mechanism (Clojure's evaluator) as LC's application mechanism
So you're actually writing a clojure program (not an LC program) that is subject to the effects of the clojure compiler/evaluator – which means strict evaluation and non-constant-space direction recursion. Let's look at:
(def add2 (fn [f]
(fn [a]
(fn [b]
(((zero? b) a) ((f (succ a)) (pred b)))))))
As a Clojure program, in a strictly evaluated environment, each time we call add2, we evaluate
(zero? b) as value1
(value1 a) as value2
(succ a) as value3
(f value2) as value4
(pred b) as value5
(value2 value4) as value6
(value6 value5)
We can now see that calling to add2 always results in call to the recursion mechanism f – of course the program never terminates and we get a stack overflow!
You have a few options
per #amalloy's suggestions, use thunks to delay the evaluation of certain expressions and then force (run) them when you're ready to continue the computation – tho I don't think this is going to teach you much
you can use Clojure's loop/recur or trampoline for constant-space recursions to implement your Y or Z combinator – there's a little hang-up here tho because you're only wishing to support single-parameter lambdas, and it's going to be a tricky (maybe impossible) to do so in a strict evaluator that doesn't optimise tail calls
I do a lot of this kind of work in JS because most JS machines suffer the same problem; if you're interested in seeing homebrew workarounds, check out: How do I replace while loops with a functional programming alternative without tail call optimization?
write an actual evaluator – this means you can decouple your the representation of your Lambda Calculus program from datatypes and behaviours of Clojure and Clojure's compiler/evaluator – you get to choose how those things work because you're the one writing the evaluator
I've never done this exercise in Clojure, but I've done it a couple times in JavaScript – the learning experience is transformative. Just last week, I wrote https://repl.it/Kluo which is uses a normal order substitution model of evaluation. The evaluator here is not stack-safe for large LC programs, but you can see that recursion is supported via Curry's Y on line 113 - it supports the same recursion depth in the LC program as the underlying JS machine supports. Here's another evaluator using memoisation and the more familiar environment model: https://repl.it/DHAT/2 – also inherits the recursion limit of the underlying JS machine
Making recursion stack-safe is really difficult in JavaScript, as I linked above, and (sometimes) considerable transformations need to take place in your code before you can make it stack-safe. It took me two months of many sleepless nights to adapt this to a stack-safe, normal-order, call-by-need evaluator: https://repl.it/DIfs/2 – this is like Haskell or Racket's #lang lazy
As for doing this in Clojure, the JavaScript code could be easily adapted, but I don't know enough Clojure to show you what a sensible evaluator program might look like – In the book, Structure and Interpretation of Computer Programs,
(chapter 4), the authors show you how to write an evaluator for Scheme (a Lisp) using Scheme itself. Of course this is 10x more complicated than primitive Lambda Calculus, so it stands to reason that if you can write a Scheme evaluator, you can write an LC one too. This might be more helpful to you because the code examples look much more like Clojure
a starting point
I studied a little Clojure for you and came up with this – it's only the beginning of a strict evaluator, but it should give you an idea of how little work it takes to get pretty close to a working solution.
Notice we use a fn when we evaluate a 'lambda but this detail is not revealed to the user of the program. The same is true for the env – ie, the env is just an implementation detail and should not be the user's concern.
To beat a dead horse, you can see that the substitution evaluator and the environment-based evaluator both arrive at the equivalent answers for same input program – I can't stress enough how these choices are up to you – in SICP, the authors even go on to change the evaluator to use a simple register-based model for binding variables and calling procs. The possibilities are endless because we've elected to control the evaluation; writing everything in Clojure (as you did originally) does not give us that kind of flexibility
;; lambda calculus expression constructors
(defn variable [identifier]
(list 'variable identifier))
(defn lambda [parameter body]
(list 'lambda parameter body))
(defn application [proc argument]
(list 'application proc argument))
;; environment abstraction
(defn empty-env []
(hash-map))
(defn env-get [env key]
;; implement
)
(defn env-set [env key value]
;; implement
)
;; meat & potatoes
(defn evaluate [env expr]
(case (first expr)
;; evaluate a variable
variable (let [[_ identifier] expr]
(env-get env identifier))
;; evaluate a lambda
lambda (let [[_ parameter body] expr]
(fn [argument] (evaluate (env-set env parameter argument) body)))
;; evaluate an application
;; this is strict because the argument is evaluated first before being given to the evaluated proc
application (let [[_ proc argument] expr]
((evaluate env proc) (evaluate env argument)))
;; bad expression given
(throw (ex-info "invalid expression" {:expr expr}))))
(evaluate (empty-env)
;; ((λx.x) y)
(application (lambda 'x (variable 'x)) (variable 'y))) ;; should be 'y
* or it could throw an error for unbound identifier 'y; your choice
I'm writing a program that uses classical cons pairs a la Common Lisp, Scheme, et al.
(deftype Cons [car cdr]
clojure.lang.ISeq
(first [c] (.car c))
(more [c] (.cdr c))
I create lists by chaining cons cells, e.g. (Cons. a (Cons. b nil)) for the list containing a and b. I wrote a function to convert a Clojure collection into a cons list:
(defn conslist [xs]
(if (empty? xs)
nil
(Cons. (first xs) (conslist (rest xs)))))
This works but will overflow if xs is too big. recur doesn't work because the recursive call isn't in a tail position. Using loop with an accumulator wouldn't work, because cons only puts stuff at the front, when each recurse gives you the next item, and I can't use conj.
What can I do?
Edit: In the end, it turns out if you get this working, Clojure fundamentally isn't designed to support cons pairs (you can't set the tail to a non-seq). I ended up just creating a custom data structure and car/cdr functions.
as usual, i would propose the simplest loop/recur:
(defn conslist [xs]
(loop [xs (reverse xs) res nil]
(if (empty? xs)
res
(recur (rest xs) (Cons. (first xs) res)))))
lazy-seq is your friend here. It takes a body that evaluates to an ISeq, but the body will not be evaluated until the result of lazy-seq is invoked.
(defn conslist [xs]
(if (empty? xs)
nil
(lazy-seq (Cons. (first xs) (conslist (rest xs))))))
I have a recursive function which needs to recurse until it finds a certain result. However in the body of my function after my first recursive call I might do some other calculations or possibly recurse again. But, if I recurse and find the result I'm looking for, then I'd like to just stop out of any recursive I've been doing and return that result to avoid doing unnecessary computations.
In a normal recursive call once you get to the "base case" that gets returned to the function that called, then that gets returned to the one that called it, and so on. I'd like to know how to just return to the very first time the function was called, and not have to return something for all those intermediate steps.
For my basic recursion I could write a function like this:
(defun recurse (x)
(if (= x 10)
(return-from recurse x)
(progn (recurse (+ x 1)) (print "Recursed!")))))
(recurse 1)
It has been written to illustrate what I mean about the function running more computations after a recursive call. And, as written this doesn't even return the value I'm interested in since I do some printings after I've returned the value I care about. (Note: The return-from command is extraneous here as I could just write "x" in its place. It's just there to draw parallels for when I try to return to the top level recursion in my second example below.)
Now, if I want to ditch all those extra "Recursed!" printings I could encase everything in a block and then just return to that block instead:
EDIT: Here is a function wrapper for my original example. This example should be clearer now.
(defun recurse-to-top (start)
(block top-level
(labels ((recurse (x)
(if (= x 10)
(return-from top-level x)
(progn (recurse (+ x 1)) (print "Recursed!")))))
(recurse start))))
And running this block keeps going until 10 "is found" and then returns to from the top-level block with no extraneous printing, just like I wanted. But, this seems like a really clunky way to get this feature. I'd like to know if there's a standard or "best" way for getting this type of behavior.
DEFUN already sets up a lexical block:
(defun recurse (start)
(labels ((recurse-aux (x)
(case x
(10 (return-from recurse x))
(15 x)
(otherwise
(recurse-aux (+ x 1))
(print "Recursed!")))))
(recurse-aux start)))
Older is the use of CATCH and THROW, which is a more dynamic construct and thus allows an exit across functions:
(defun recurse (start)
(catch 'recurse-exit
(recurse-aux start)))
(defun recurse-aux (x)
(case x
(10 (throw 'recurse-exit x))
(15 x)
(otherwise
(recurse-aux (+ x 1))
(print "Recursed!")))))
(recurse-aux start))))
As mentioned by Lars, there are even more way to program control flow like this.
You want some kind of non-local exit. There are a few choices: return-from, go, throw, signal.
Maybe some variation on this?
(defun recurse (x &optional (tag 'done))
(catch tag
(when (= x 10)
(throw 'done x))
(recurse (1+ x) nil)
(print "Cursed!")))
I believe it does what you want, although there may be a lot of needless catching going on.
As always with Lisp, you can imagine there is a perfect language for your problem, and write your program in that language. E.g. something like
(defun recurse (x)
(top-level-block recurse
(when (= x 10)
(return-from-top-level recurse x))
(recurse (1+ x))
(print "Cursed!")))
Then there is just a simple matter of programming to implement the new macros top-level-block and return-from-top-level.
Imperfect sample code follows:
(defmacro top-level-block (name &body body)
`(if (boundp ',name)
(progn ,#body)
(catch ',name
(let ((,name t))
(declare (special ,name))
,#body))))
(defmacro return-from-top-level (name value)
`(throw ',name ,value))
How can I test that every value in the collection returned by map is true?
I am using the following:
(defn test [f coll]
(every? #(identity %) (map f coll)))
with the anonymous function #(identity %), but I was wondering if there is a better way.
I cannot use (apply and ...) because and is a macro.
UPDATE: BTW, I am making my way through The Haskell Road to Logic, Maths, and Programming, by Kees Doets and Jan can Eijck, but doing the exercises in Clojure. It's a very interesting book.
either
(every? identity (map f coll))
or
(every? f coll)
You can do:
(every? true? coll)
I wrote this quicksort function:
(defun quicksort (lst)
(if (null lst)
nil
(let ((div (car lst))
(tail (cdr lst)))
(append (quicksort (remove-if-not (lambda (x) (< x div)) tail))
(list div)
(quicksort (remove-if (lambda (x) (< x div)) tail))))))
but I can't rewrite it as macro, it does not work, nor does, for example, this simple foo (recursive sum - I know, a little silly, but just as example):
(defun Suma (lst)
(if (cdr lst)
(+ (Suma (cdr lst))
(car lst))
(car lst)))
works properly, but the macro:
(defmacro SumaMacro (lst)
'(if (cdr lst)
'(+ (prog (SUMAMACRO (cdr lst)))
(prog (car lst)))
'(car lst)))
seems to be wrong. Does someone have any suggestions about rewriting recursive functions as macro?
You're mixing macro and runtime; or in other words, you're mixing values and syntax. Here's a very simple example:
(defmacro while (condition &body body)
`(when ,condition ,#body (while ,condition ,#body)))
The bad thing here is that the macro doesn't execute the body, it just constructs a piece of code with the given body in it. So, when there's that kind of a loop in a function, it's protected by some conditional like if which will prevent an infinite loop. But in this macro code there is no such condition -- you can see that the macro expands into the exact original form, which means that it's trying to expand into some infinite piece of code. It's just as if you've written
(defun foo (blah)
(cons 1 (foo blah)))
then hooked that generator function into the compiler. So to do these kinds of runtime loops, you'll have to use a real function. (And when that's needed, you can use labels to create a local function to do the recursive work.)
It makes no sense to write recursive functions like SUM or QUICKSORT as macros. Also, no, in general it is not possible. A macro expands source code. At compile time the macro sees only the source code, but not the real arguments the code is being called with. After compilation the macros is gone and replaced with the code it produces. This code then later gets called with arguments. So the macro can't do computation at compile time, based on argument values that are known only at runtime.
The exception is: when the argument value is known at compile time / macro expansion time, then the macro can expand to a recursive macro call to itself. But that is really advanced macro usage and nothing that one would add to code to be maintained by other programmers.
Rule of thumb: If you want to do recursive computations, then use functions. If you want to process source code, then use a macro.
Also, try to use Lisp-like formatting. The editor counts the parentheses, does highlighting and indentation. Don't put parentheses on their own lines, they feel lonely there. The usual Lisp style is more compact and uses also the horizontal space more. If you work with lists, then use FIRST and REST, instead of CAR and CDR.
Your 'suma' function would look like this:
(defun suma (list)
(if (rest list)
(+ (suma (rest list))
(first list))
(first list)))
Forget about the macro. But, if you want to learn more about macros, then the book 'On Lisp' by Paul Graham (available as a download) is a good source of knowledge.