Prolog translation of Lisp's tail-recursion - prolog

I have a question that is a followup to a previous topic,
Should I avoid tail recursion in Prolog and in general?
In the above linked article , user false
provided this code example and this explanation ...
Back in the 1970s, the major AI language was LISP. And the
corresponding definition would have been ...
(defun addone (xs)
(cond ((null xs) nil)
(t (cons (+ 1 (car xs))
(addone (cdr xs))))))
... which is not directly tail-recursive: The reason is the cons:
In implementations of that time, its arguments were evaluated first,
only then, the cons could be executed. So rewriting this as you have
indicated (and reversing the resulting list) was a possible
optimization technique.
In Prolog, however, you can create the cons prior to knowing the
actual values, thanks to logic variables. So many programs that were
not tail-recursive in LISP, translated to tail-recursive programs in
Prolog.
The repercussions of this can still be found in many Prolog
textbooks.
My question is : what is a good Prolog translation of the above
LISP code ?
EDIT: added the example of the lisp code in action and the
lisp documentation describing the various lisp functions .
example of addone in action
1 > (addone '(1 2 3))
(2 3 4)
2 > (addone '('()))
> Error: The value 'NIL is not of the expected type NUMBER.
> While executing: CCL::+-2, in process listener(1).
> Type :POP to abort, :R for a list of available restarts.
> Type :? for other options.
3 > (addone '(a b c))
> Error: The value A is not of the expected type NUMBER.
> While executing: CCL::+-2, in process listener(1).
> Type :POP to abort, :R for a list of available restarts.
> Type :? for other options.
3 > ^C
documentation of lisp features
cons object-1 object-2 => cons
Creates a fresh cons ,
the car of which is object-1 ,
and the cdr of which is object-2 .
Examples
(cons 1 2) => (1 . 2)
(cons 1 nil) => (1)
(cons nil 2) => (NIL . 2)
(cons nil nil) => (NIL)
(cons 1 (cons 2 (cons 3 (cons 4 nil)))) => (1 2 3 4)
(cons 'a 'b) => (A . B)
(cons 'a (cons 'b (cons 'c '()))) => (A B C)
(cons 'a '(b c d)) => (A B C D)
(car x) => object
If x is a cons ,
car returns the car of that cons .
If x is nil ,
car returns nil .
(cdr x) => object
If x is a cons ,
cdr returns the cdr of that cons .
If x is nil ,
cdr returns nil
.
cond {clause}* => result*
clause::= (test-form form*)
Test-forms are evaluated one at a time in the order in which they
are given in the argument list until a test-form is found that
evaluates to true .
If there are no forms in that clause, the primary value of the
test-form [ed: the first value of the test-form , or nil if there
are no values] is returned by the cond form. Otherwise, the forms
associated with this test-form are evaluated in order, left to
right, as an implicit progn, and the values returned by the last
form are returned by the cond form.
Once one test-form has yielded true, no additional test-forms are
evaluated. If no test-form yields true, nil is returned
See
http://www.lispworks.com/documentation/HyperSpec/Body/m_cond.htm#cond
for more information .
defun function-name lambda-list form* => function-name
See
http://www.lispworks.com/documentation/HyperSpec/Body/m_defun.htm#defun
for more information .
t => T
t => T
(eq t 't) => T
(case 'b (a 1) (t 2)) => 2

Here's a rendition in Prolog of the given Lisp algorithm. Note that Lisp is functional and a Lisp function can return values. This isn't the case in Prolog, so you need two arguments.
A direct implementation, which is not relational, would be:
addone([], []).
addone([H|T], [H1|T1]) :-
H1 is H + 1,
addone(T, T1).
Note that the [H1|T1] argument in the head of the second predicate clause corresponds to (cons H1 T1) in Lisp.
This can also be done using maplist, which steps a little bit away from the original Lisp implementation, but Lisp does have list mapping functions which could be used to create a Lisp implementation that would look more like this:
addone_element(X, X1) :- X1 is X + 1.
addone(List, List1) :- maplist(addone_element, List, List1).
In Prolog this can be made more relational using CLP(FD) which is useful for reasoning over integers:
:- use_module(library(clpfd)).
addone([], []).
addone([H|T], [H1|T1]) :-
H1 #= H + 1,
addone(T, T1).
And the maplist version:
addone_element(X, X1) :- X1 #= X + 1.
addone(List, List1) :- maplist(addone_element, List, List1).

A direct translation:
(defun addone (xs)
(cond ((null xs) nil)
(t (cons (+ 1 (car xs))
(addone (cdr xs))))))
is
addone( XS, RESULT) :-
( XS = [], % null XS ? then:
RESULT = [] %
;
XS = [CAR | CDR], % else:
R is 1 + CAR, % calculate the two
addone( CDR, S) % fields % almost TR,
RESULT = [R | S], % and cons them up % save for this cons
).
But, transformed,
(defun addone (xs)
(let ((result))
(cond ((null xs) (setf result nil))
(t (setf result (cons (+ 1 (car xs))
(addone (cdr xs))))))
result))
=
(defun addone (xs)
(let ((result))
(cond ((null xs) (setf result nil))
(t (setf result (list nil))
(setf (car result) (+ 1 (car xs)))
(setf (cdr result) (addone (cdr xs)))))
result))
=
(defun addone (xs &optional (result (list nil))) ; head sentinel
(cond ((null xs))
(t (setf (cdr result) (list nil))
(setf (cadr result) (+ 1 (car xs)))
(addone (cdr xs) (cdr result)))) ; almost TR
(cdr result)) ; returned but not used
=
(defun addone (xs &aux (result (list nil)))
(labels ((addone (xs result)
(cond ((null xs))
(t (setf (cdr result) (list nil))
(setf (cadr result) (+ 1 (car xs)))
(addone (cdr xs) (cdr result)))))) ; fully TR
(addone xs result))
(cdr result))
it is, fully tail recursive,
addone( XS, RESULT) :-
( XS = [],
RESULT = []
;
XS = [CAR | CDR],
RESULT = [R | S], % cons two empty places, and
R is 1 + CAR, % fill'em
addone( CDR, S) % up % fully TR
).
Boxing / head sentinel is used so we can have settable pointers in Common Lisp, but in Prolog this isn't needed -- Prolog's logical variables are directly settable (once), named pointers.
This is also the reason why Prolog's transformation is so much smaller and easier than Lisp's. All it took was moving one line of code up a notch or two (and it could've been one just the same).

Related

How do collector functions work in Scheme?

I am having trouble understanding the use of collector functions in Scheme. I am using the book "The Little Schemer" (by Daniel P. Friedman and Matthias Felleisen). A comprehensive example with some explanation would help me massively. An example of a function using a collector function is the following snippet:
(define identity
(lambda (l col)
(cond
((null? l) (col '()))
(else (identity
(cdr l)
(lambda (newl)
(col (cons (car l) newl))))))))
... with an example call being (identity '(a b c) self) and the self-function being (define self (lambda (x) x)). The identity function returns the given list l, so the output of the given call would be (a b c). The exact language used is the R5RS Legacy-language.
Given how those "collector" functions are defined in the identity definition, calling
(identity xs col)
for any list xs and some "collector" function col, is equivalent to calling
(col xs)
so the same list will be "returned" i.e. passed to its argument "collector" / continuation function col. That explains its name, identity, then.
For comparison, a reverse could be coded as
(define reverse ; to be called as e.g. (reverse l display)
(lambda (l col)
(cond
((null? l) (col '())) ; a reversed empty list is empty
(else (reverse (cdr l) ; a reversed (cdr l) is newl --
(lambda (newl) ; what shall I do with it when it's ready?
(col ; append (car l) at its end and let col
(append newl ; deal with it!
(list (car l))))))))))
This style of programming is known as continuation-passing style: each function is passed a "continuation" that is assumed that it will be passed the result of the rest of computation, so that the original continuation / collector function will be passed the final result eventually. Each collector's argument represents the future "result" it will receive, and the collector function itself then specifies how it is to be handled then.
Don't get confused by the terminology: these functions are not "continuations" captured by the call/cc function, they are normal Scheme functions, representing "what's to be done next".
The definition can be read as
identity :
to transform a list xs
with a collector function col,
is
| to call (col xs) , if xs is empty, or
| to transform (cdr xs)
with a new collector function col2
such that
(col2 r) = (col (cons (car xs) r)) , otherwise.
(or we can write this in a pseudocode, as)
(identity list col) =
| empty? list -> (col list)
| match? list (x . xs) -> (identity xs col2)
where
(col2 r) = (col (cons x r))
col2 handles its argument r by passing (cons x r) to the previous handler col. This means r is transformed into (cons x r), but instead of being returned as a value, it is fed into col for further processing. Thus we "return" the new value (cons x r) by passing it to the previous "collector".
A sample call, as an illustration:
(identity (list 1 2 3) display)
= (identity (list 2 3) k1)
; k1 = (lambda (r1) (display (cons 1 r1))) = display ° {cons 1}
= (identity (list 3) k2)
; k2 = (lambda (r2) (k1 (cons 2 r2))) = k1 ° {cons 2}
= (identity (list ) k3)
; k3 = (lambda (r3) (k2 (cons 3 r3))) = k2 ° {cons 3}
= (k3 '()) ; (((display ° {cons 1}) ° {cons 2}) ° {cons 3}) []
= (k2 (cons 3 '())) ; ((display ° {cons 1}) ° {cons 2}) [3]
= (k1 (cons 2 (list 3))) ; (display ° {cons 1}) [2,3]
= (display (cons 1 (list 2 3))) ; display [1,2,3]
= (display (list 1 2 3))
update: in a pattern-matching pseudocode I've been fond of using as of late, we could write
identity [] col = col []
identity [a, ...d] col = identity d ( newl => col [a, ...newl] )
and
reverse [] col = col []
reverse [a, ...d] col = reverse d ( newl => col [...newl, a] )
which hopefully is so much visually apparent that it almost needs no explanation!
I'm adding the second answer in the hopes it can clarify the remaining doubts in case you have any (as the lack of the "accepted" mark would indicate).
In the voice of Gerald J. Sussman, as heard/seen in the SICP lectures of which the videos are available here and there on the internet tubes, we can read it as we are writing it,
(define identity
"identity" is defined to be
(lambda
that function which, when given
(l col)
two arguments, l and col, will
(cond
((null? l)
-- in case (null? l) is true --
OK, this means l is a list, NB
(col '()))
return the value of the expression (col '())
OK, this now means col is a function, expecting of one argument, as one possibility an empty list,
(else (identity (cdr l)
or else it will make a tail recursive call with the updated values, one being (cdr l),
(lambda (newl)
(col (cons (car l) newl)))))))
and the other a newly constructed function, such that when it will be called with its argument newl (a list, just as was expected of col -- because it appears in the same role, it must follow the same conventions), will in turn call the function col with the non-empty list resulting from prefixing (car l) to the list newl.
Thus this function, identity, follows the equations
( identity (cons (car l) (cdr l)) col )
==
( identity (cdr l) (lambda (newl) (col (cons (car l) newl))) )
and
( identity '() col )
==
( col '() )
describing an iterative process, the one which turns the function call
(identity [a, b, c, ..., n] col )
into the call
(col
(cons a (cons b (cons c ... (cons n '()) ... ))))
recreating the same exact list anew, before feeding it as an argument to the function col it has been supplied with.

contract violation in my implementation of "map"

I'm beginning in Scheme (actually, Racket with DrRacket) and I want to practice by implementing a map function (apply a function to all elements of a list), but there's something wrong that I don't understand.
(I have, aside from my imperative background, a basic knowledge of haskell)
I want to translate the following piece of haskell (Just to show the algorithm) :
map f [] = []
map f x:xs = (f x) : (map f xs)
Here's my code :
(define (map f xs)
(if (= xs '()) '() ; if list is empty, return empty list
(cons (f (car xs)) (map f (cdr xs))))
)
To test it, I used this :
(define (testFunction x) (+ x 1))
(define testList '(1 2 3 4 5))
(map testFunction testList)
And I get the following error :
=: contract violation
expected: number ?
given : '(1 2 3 4 5)
argument position: 1st
other arguments...:
which highlights the predicate (= xs '())
Any tips ?
The = function is specifically for equality between numbers. It has special handling for numeric values by handling comparisons between exact and inexact numbers. In general, though, for non-numeric equality, you should use the equal? predicate:
> (equal? '() '())
#t
In this particular case, as mentioned by Raghav, you can also use empty? or null? to test for the empty list (the empty? predicate is just an alias for null?).
Wow - a few others already beat me to it, but I'll share my answer, anyways.
Your issue stems from your use of = to test list emptiness.
From the = in the docs:
Returns #t if all of the arguments are numerically equal, #f
otherwise.
In order to get your program working, I'd suggest using equal? to test the two lists for equality or, better yet, use empty? or null? to test if xs is an empty list. (I hope you don't take offense, but I've also massaged the code into what's (arguably) more idiomatic Scheme).
(define (mymap f xs)
(if (empty? xs)
xs
(cons
(f (car xs))
(mymap f (cdr xs)))))
(define (test-function x) (+ x 1))
(define test-list (list 1 2 3 4))
(mymap test-function test-list)
If you're using DrRacket, then for that condition, simply use (empty?):
(if (empty? xs)
xs ; because xs is empty
...)

filter function using tail recursion

Currently I have
(define filter
(λ (f xs)
(letrec [(filter-tail
(λ (f xs x)
(if (empty? xs)
x
(filter-tail f (rest xs)
(if (f (first xs))
(cons (first xs) x)
'()
)))))]
(filter-tail f xs '() ))))
It should be have as a filter function
However it outputs as
(filter positive? '(-1 2 3))
>> (3 2)
but correct return should be (2 3)
I was wondering if the code is correctly done using tail-recursion, if so then I should use a reverse to change the answer?
I was wondering if the code is correctly done using tail-recursion.
Yes, it is using a proper tail call. You have
(define (filter-tail f xs x) ...)
Which, internally is recursively applied to
(filter-tail f
(some-change-to xs)
(some-other-change-to x))
And, externally it's applied to
(filter-tail f xs '())
Both of these applications are in tail position
I should use a reverse to change the answer?
Yep, there's no way around it unless you're mutating the tail of the list (instead of prepending a head) as you build it. One of the comments you received alluded to this using set-cdr! (see also: Getting rid of set-car! and set-cdr!). There may be other techniques, but I'm unaware of them. I'd love to hear them.
This is tail recursive, requires the output to be reversed. This one uses a named let.
(define (filter f xs)
(let loop ([ys '()]
[xs xs])
(cond [(empty? xs) (reverse ys)]
[(f (car xs)) (loop (cons (car xs) ys) (cdr xs))]
[else (loop ys (cdr xs))])))
(filter positive? '(-1 2 3)) ;=> '(2 3)
Here's another one using a left fold. The output still has to be reversed.
(define (filter f xs)
(reverse (foldl (λ (x ys) (if (f x) (cons x ys) ys))
'()
xs)))
(filter positive? '(-1 2 3)) ;=> '(2 3)
With the "difference-lists" technique and curried functions, we can have
(define (fold c z xs)
(cond ((null? xs) z)
(else (fold c (c (car xs) z) (cdr xs)))))
(define (comp f g) (lambda (x) ; ((comp f g) x)
(f (g x))))
(define (cons1 x) (lambda (y) ; ((cons1 x) y)
(cons x y)))
(define (filter p xs)
((fold (lambda (x k)
(if (p x)
(comp k (cons1 x)) ; nesting's on the left
k))
(lambda (x) x) ; the initial continuation, IC
xs)
'()))
(display (filter (lambda (x) (not (zero? (remainder x 2)))) (list 1 2 3 4 5)))
This builds
comp
/ \
comp cons1 5
/ \
comp cons1 3
/ \
IC cons1 1
and applies '() to it, constructing the result list in the efficient right-to-left order, so there's no need to reverse it.
First, fold builds the difference-list representation of the result list in a tail recursive manner by composing the consing functions one-by-one; then the resulting function is applied to '() and is reduced, again, in tail-recursive manner, by virtues of the comp function-composition definition, because the composed functions are nested on the left, as fold is a left fold, processing the list left-to-right:
( (((IC+k1)+k3)+k5) '() ) ; writing `+` for `comp`
=> ( ((IC+k1)+k3) (k5 '()) ) ; and `kI` for the result of `(cons1 I)`
<= ( ((IC+k1)+k3) l5 ) ; l5 = (list 5)
=> ( (IC+k1) (k3 l5) )
<= ( (IC+k1) l3 ) ; l3 = (cons 3 l5)
=> ( IC (k1 l3) )
<= ( IC l1 ) ; l1 = (cons 1 l3)
<= l1
The size of the function built by fold is O(n), just like the interim list would have, with the reversal.

Any idea of how to interleave two lists in dr racket?

The problem is when lists have a different length, any idea of how to do it?
I have to use functions like map or something like that
This is the code I wrote so far, it works with lists of the same length but it also needs to work with lists of different lengths. Thank you.
(define (interleave list1 list2)
(flatten [map (lambda (x y) (cons x (cons y null))) list1 list2]))
if lists have different length this is what I get:
map: all lists must have same size; arguments were: # '(1 2 3 4 5) '(a b c)
I'm trying to get (1 a 2 b 3 c 4 5)
#lang racket
(define (weave xs ys)
(match (list xs ys)
[(list (cons x xs) (cons y ys)) (cons x (cons y (weave xs ys)))]
[(list '() ys) ys]
[(list xs '()) xs]))
I'm assuming your desired behavior is that the lists are interleaved for as long as this is possible, and then whatever is left over from the nonempty list is appended to the end. In that case one possible implementation is
(define (interleave a b)
(if (null? a)
b
(cons (car a)
(interleave b (cdr a)))))
I think this is probably the simplest possible way to write what you're looking for.
Neither map nor fold-right would work because they either signal an error when one list is smaller than the other or they tend to stop at the shortest list. eg. SRFI-1's map (interleave '(1 2 3 4) (circular-list 9 8)) ; ==> (1 9 2 8 3 9 4 8). For a different behavior you need to roll your own.
A solution using simple list manipulation functions might be:
(define (interleave list1 list2)
(cond ((empty? list1) list2)
((empty? list2) list1)
(else
(append
(list (car list1) (car list2))
(interleave (cdr list1) (cdr list2))))))
Testing...
> (interleave '(1 2 3 4 5) '(a b c))
(1 a 2 b 3 c 4 5)
> (interleave '(1 2 3 4 5) '())
(1 2 3 4 5)
> (interleave '() '(a b c))
(a b c)
>
I think it is fairly self-documenting.
"There ain't nothin' you can't not do with fold-right and some of them con-tin-uations thingies", said a cowboy to another, spittin' into the campfire and puffin' on his cigar in the evening, sippin' his black coffee from his rugged banged up tin mug. "Yessa, nothin' in the whole darn world."
(define (interleave xs ys)
;; interleave xs ys = foldr g n xs ys
;; where
;; g x r (y:ys) = x : y : r ys
;; g x r [] = x : r []
;; n ys = ys
((foldr
(lambda (x r)
(lambda (ys)
(cond ((null? ys) (cons x (r '())))
(else (apply (lambda (y . ys)
(cons x (cons y (r ys))))
ys)))))
(lambda (ys) ys)
xs)
ys))

Using racket structs for summing elements at even and odd positions

In class we wrote an interpreter for a made up language (lanG) using the following racket structs.
(struct const (n))
(struct bool (b))
(struct join (e1 e2))
(struct if-then-else (b e1 e2))
(struct negate (e))
(struct add (e1 e2))
(struct multiply (e1 e2))
(struct head (e)) ;returns the head of the list
(struct tail (e)) ;returns the tail of the list
(struct biggerThan (e1 e2))
Macros for this language are defined as racket functions. A simple example would be:
(define (threeTimes x)
(add x (add x x)))
And using it would look like:
(lanG (threeTimes (const 3)))
which would produce an answer:
(const 9)
Now to my problem. There was a task on the exam where we had to write a macro sumAtEvenAndOdd, which would sum a list of lanG constants,
made with the join struct and return a pair of values consisting of the sum of elements at even positions and the sum of elements
at the odd positions.
An example of such a list would be:
(join (const 3) (join (const 2) (const 5))) ;lanG list with no null at the end
And its result would be:
(join (const 2) (const 8))
I tried solving this by converting the list into a racket list, ziping the positions with the elements, filtering the odd or even elements out of the list,
and producing the pair using the sums of those lists. This works but I am overcomplicating. Professor said the solution is about 5 lines long.
I thank you in advance for all your help.
I assume there are also predicates to identify a const and a join - let's call them const? and join?.
Supposing we had a function for adding up every other item of a list, sumAtEvenAndOdd could look like this:
(define (sumAtEvenAndOdd xs)
(join (sumEveryOther (tail xs)) (sumEveryOther xs)))
and then sumEveryOther could be implemented like this:
(define (sumEveryOther x)
(if-then-else (const? x)
x
(if-then-else (join? (tail x))
(add (head x) (sumEveryOther (tail (tail x))))
(head x))))
This is of course not optimal, since it traverses the list twice, but it's short ("exam-size") and implemented entirely within lanG.
A slightly longer solution that only traverses the list once, using accumulators:
(define (sumEvenOdd x evens odds odd?)
(if-then-else (const? x)
(if-then-else odd?
(join evens (add odds x))
(join (add evens x) odds))
(if-then-else odd?
(sumEvenOdd (tail x) evens (add (head x) odds) (negate odd?))
(sumEvenOdd (tail x) (add (head x) evens) odds (negate odd?)))))
(define (sumAtEvenAndOdd xs)
(sumEvenOdd xs 0 0 (bool #t)))
So join is like a pair where join-e2 could be a join?. To loop through it you do the same as with pair? with a dotted list since a proper list in you example ended with a const.
(let loop ((lst '(1 2 3 4 5 6 . 7)) (o 0) (e 0) (odd? #t))
(let* ((ele (if (pair? lst) (car lst) lst))
(no (if odd? (+ ele o) o))
(ne (if odd? e (+ ele e))))
(if (pair? lst)
(loop (cdr lst) no ne (not odd?))
(cons no ne))))
Here is a simple recursive solution.
(define (sum-even/odd xs)
(if (null? xs)
(values 0 0)
(call-with-values
(λ () (sum-even/odd (cdr xs)))
(λ (e o) (values (+ (car xs) o) e)))))
> (sum-even/odd '(1 2 3 4 5 6 7))
16
12

Resources