How to reference a recursive variable within a macro in racket - recursion

In Drracket I am being tasked with creating a recursive macro that can take in (edges n1 -> n2 <-> n3) for example, with n1, n2, and n3 being (define-struct node (name edges)). The -> indicates putting the second node into the edges of the first node and the <-> indicates doing it both ways. So n1 would have edges n2 and n2 would have edges n3 and n3 would have edges n2. My problem lies in Drracket recursive macros. When you have a variable with an ellipse after it, ex: (edges n1 -> n2 ...) in the pattern matcher, I don't know how to reference just n2 without also evaluating the ellipse.
(define-syntax edges
(syntax-rules (-> <->)
[(edges n1 -> n2 ...)
(begin
(set-node-edges! n1 (cons (n2 ...) (node-edges n1)))
(edges n2 ...))]
[(edges n1 <-> n2 ...)
(begin
(begin
(set-node-edges! n1 (cons (n2 ...) (node-edges n1)))
(set-node-edges! n2 ... (cons 'n1 (node-edges n2 ...))))
(edges n2 ...))]
[(edges n1)
void]))

The problem is with the patterns you've used, the parens are actually tightly bound with the n2. That is n2 is a list of everything else. What you actually want is a pattern that is something more like:
n1 -> n2 rest ...
That way, the ... is bound to the rest, rather than the n2.
I also recommend using syntax-parse instead of syntax-rules. It allows for much more clear pattern matching (as well as arbitrary computations. For example, right now you are assuming that n1 and n2 are identifiers, but you aren't checking it. Your macro also requres -> and <-> to be bound outside of that macro. With syntax-parse, the whole thing becomes much cleaner:
#lang racket
(require (for-syntax syntax/parse)) ;; <-- Needed to use syntax-parse
(define-syntax (edges stx)
(syntax-parse stx
#:datum-literals (-> <->)
[(_)
#'(begin)]
[(_ n1:id -> n2:id rest ...)
#'(begin .... your code here ....)]
[(_ n1:id <-> n2:id rest ...)
#'(begin .... your code here ....)]))
Inside of the .... your code here .... blocks, you can use n1 to refer to n1:id, you can use n2 to refer to n2:id, and finally, you can use something like (n2 rest ...) to refer to a list starting with n2:id and finishing with rest ....
Also, note that by putting :id at the end of the patterns, you get automatic checking that n1 and n2 are identifiers.

Related

Isabelle recursive function

I have the following recursive function that creates a list of 0s (i.e. [0,...,0]) in VDM. How can this be translated to Isabelle using fun-where?
VDM:
NewList: nat1 * seq of nat -> seq of nat
NewList(n, l) ==
if len l = n then l
else NewList(n, l ^ [0])
-- pre/post-conditions excluded here
My attempts are horribly wrong due to my lack of understanding of Isabelle (but below at least proves that I tried...).
Isabelle:
fun
NewList:: "N ⇒ (VDMNat VDMSeq) ⇒ (VDMNat VDMSeq)"
where
"NewList n [] = NewList n [0]"
| "NewList n [x] = (if len [x] = n then [x] else NewList n (x#[0]))"
| "NewList n (x # xs) = (if len (x # xs) = n then (x # xs) else NewList n ((x # xs) # [(0::VDMNat)]))"
*The data types VDMNat and VDMSeq are defined in some library. Please ignore the VDMNat and VDMSeq for now - any sort of implementation using Isabelle's data types are welcome (at least it would provide a good reference for my implementation). Please refer to the VDM code for the data types intended.
Could you also please explain what x, xs, and (x # xs) are referring to? I've seen this in several recursive function examples (though none helps me).
Thank you for your help!
First of all, x and xs are variables. When definiting recursive functions on lists, these are often used to denote the first element of the list (x) and the remaining list (xs). The expression x # xs means ‘x prepended to the list xs’, and that is the reason why (x # xs) # [0] in your question does not work: x # xs is a list and [0] is also a list. You would have to do x # xs # [0}, where # is the function to concatenate two lists.
Now, to your function: My interpretation of your function definition is that you have a natural number n and a list l and want to pad the list l with zeros at the back up to length n.
However, when the list l is of length > n to begin with, your function does not terminate. You would have to think about what to do in that case.
Here are my suggestions for what you could do:
Possibility 1
Change the = n to a ≥ n. Then you can prove termination of the function by looking at
function new_list :: "nat ⇒ nat list ⇒ nat list" where
"new_list n l = (if length l ≥ n then l else new_list n (l # [0]))"
by pat_completeness auto
termination by (relation "measure (λ(n, l). n - length l)") auto
However, proving theorems about this will probably get ugly. I would therefore urge you to do something like the following two possibilities. Ideally, use functions from Isabelle's standard library, because there is usually good automation setup for them. Alternatively, define your own small building blocks (like take and replicate) for your datatypes and prove reusable facts on them and combine them to do what you want. A ‘monolithic’ function definition like yours is difficult to work with when doing proofs.
Possibility 2
Use the builtin function replicate, which takes a natural number n and an element and returns a list of n times that element:
definition new_list :: "nat ⇒ nat list ⇒ nat list" where
"new_list n l = l # replicate (n - length l) 0"
You can also do the same thing with fun, but definition is the more low-level tool. Note that definition does not add the function definition theorem new_list_def as a simplifier rule; you can do this by writing declare new_list_def [simp].
Possibility 3
You can combine possibility 2 with the builtin function take to ensure that you always get a list of length exactly n, even when the input list is longer (it is then possibly truncated):
definition new_list :: "nat ⇒ nat list ⇒ nat list" where
"new_list n l = take n l # replicate (n - length l) 0"
Summary
In the first two cases, you can prove the theorems
length l ≤ n ⟹ length (new_list n l) = n
take (length l) (new_list n l) = l
(in the first case by induction using new_list.induct; in the second case just by unfolding the definition and simplifying)
In the third case, you can prove
length (new_list n l) = n
take (length l) (new_list n l) = take n l
Obviously, if length l ≤ n, the first two and the last one coincide completely.
The easy solution is: replicate n (0::nat) using the function replicate of Isabelle/HOL's library.
If you want to implement the function yourself via fun then do what you should always do in functional programming ;) try to split your problem into smaller problems that can be solved recursively:
fun newlist :: "nat => nat list"
where
"newlist 0 = []" -- "the only list of length 0*)
| "newlist (Suc n) = ..." -- "use result for 'n' to obtain result for 'n+1'"

Well-definedness of function computing fixed point, in Isabelle

This is related to Project Euler problem 523.
The following algorithm sorts a list:
Starting from the beginning of the list, check each pair of adjacent elements in turn.
If the elements are out of order:
Move the smallest element of the pair at the beginning of the list.
Restart the process from step 1.
If all pairs are in order, stop.
I am attempting (for practice) to code this up in Isabelle. I have obtained the following function definitions:
fun firstpos :: "nat list ⇒ nat"
where "firstpos [] = 0"
| "firstpos (x # y # xs) = (if (x > y) then 1 else (firstpos (y#xs))+1)"
| "firstpos [x] = Suc 0"
and
fun insertAtFront :: "(nat list) ⇒ (nat) ⇒ (nat list)"
where "insertAtFront l 0 = l"
| "insertAtFront l i = [hd (rev (take i l))] # (take (i-1) l) # (rev (take ((length l) - i) (rev l)))"
where firstpos determines the list-index of the first element which is greater than its successor in the list, and insertAtFront permutes the list so that the "second argument"th element is at the front.
That is, firstPos effectively tells us where to start doing Step 2 of the algorithm, and insertAtFront is step 2.1 of the algorithm.
Now, I wish to define the function which is basically the fixed point of the composition of these. In other words,
fun sortproc :: "nat list ⇒ nat list"
where "sortproc l = sortproc (insertAtFront l (firstpos l + 1))"
It is nontrivial that this procedure ever terminates, but I can prove it mathematically: at each stage, $\sum_{i=1}^n 2^i L_{n-i}$ decreases, where $n$ is the length of list $L$.
I am a novice in Isabelle. How can I code the idea "this definition is well-defined, because of this proof" in Isabelle? The documentation seems to talk mainly about size arguments, and the size of the input isn't changing: it's always a list of the same length.

common lisp: acons in matching lists?

I'm working through The Elements of Artificial Intelligence Using Common Lisp by Steven Tanimoto and I can't figure out his match program. So far the idea is to gradually improve upon a self-rolled list match, starting with not very good
(defun match1 (p s) (equalp p s))
Here's match3:
(defun match3 (p s)
(cond
((null p) (null s)) ;null clause
((or (atom p) (atom s)) nil) ;atom clause
((equalp (first p) (first s)) ;equal CAR clause
(match3 (rest p) (rest s)))
((eql (first p) '?) ; joker clause
(match3 (rest p) (rest s)))
(t nil))) ;extremal clause
the so-called joker clause should match, i.e.,
(match3 '(a b ? d) '(a b c d)) ; yields t
but then the next version should "match" this
(match4 '((? x) b c (? y)) '(a b c d))
I quote
This would permit, for example, the (above) form to not only return
true, but also return the association of a with x and the
association of d with y. In that way, if the match is used as a
condition in a production rule, the action part of the rule can
manipulate the values matching the variable elements in the pattern.
...and then it goes on talking about alist things. Then the rewrite of match:
(defun4 match4 (p s)
(cond
((and (null p) (null s))
'((:yes . :yes)))
((or (atom p) (atom s)) nil)
((equalp (first p) (first s))
(match4 (rest p) (rest s)))
((and
(equalp (length (first p)) 2)
(eql (first (first p)) '?)
(let ((rest-match
(match4 (rest p) (rest s))))
(if rest-match
(acons (first (rest (first p)))
(first s)
rest-match)))))
(t nil)))
...so if someone could get me started by first telling me why we want to compare (? x) to a in the example above, that would help. Basically, I'm not clear on what the goal is here. If someone could explain the motivation behind this, I think I could pick apart the code. Otherwise, I'm totally lost.
match3 introduces simple pattern matching between two lists, where the symbol ? in the first list can match any single symbol in the second list. For this reason the function returns T or NIL, to denote the success or the failure of the matching process.
Then a new kind of match is introduced in match4, through the use of what appear to be a match variable. (? x) is simply a way of introducing a match variable, that in other languages could be written as ?x, or something similar. The idea is that this variable “captures” the symbol matched on the second list, so that, for instance, you could later use it in a way similar to this:
(match '(a (? x) (? y) (? x) b) '(a c d c b)) ; yes, since ‘c’ matches ‘?x’
(match '(a (? x) (? y) (? x) b) '(a c d e b)) ; no, since ‘c’ and ‘e’ are different
For this to be used effectively, the function match must give, when a match is found, not simply the value T, but the couple (match variable, symbol matched), and build with it an associative list of matches found. So, match4 returns such list through the use of acons, in the last branch of the cond (first it gets rest-match, than “aconses” over it the pair given by the match variable and the symbol found). The special pair (:yes . :yes) is simply a way of terminating this list of matches.
I suppose that later in the book will be presented another version of the match function in which the matches found will be used in the subsequent part of the process.
I have tanimoto's book, but won't have access to it until tomorrow at the earliest, but the example mentioned in the quote is actually a good one:
in that way, if the match is used as a condition in a production rule, the action part of the rule can manipulate the values matching the variable elements in the pattern.
Production rule systems are a good example of where this kind of matching is useful. It lets rule writers focus on domain knowledge, and to keep algorithms for processing rules separate.
Some approaches to functional programming also make heavy use of pattern matching. Programing language support varies, though. Common Lisp makers it easy to wrote your own though.

Is This Function Tail-Recursive? Scheme

Is the following function tail-recursive? If not, what might I do to modify it?
(define (euclids-alg n1 n2)
(cond((= n1 0) n2)
((= n2 0) n1)
((= n1 n2) n1)
((> n1 n2) (euclids-alg (- n1 n2) n2))
((< n1 n2) (euclids-alg n1 (- n2 n1)))))
Yes, your function is tail recursive, because the recursive call is in tail position - meaning, it's the last thing it's done after the recursion returns. Take a look at the specification to better understand when we have a valid tail call and when we don't.

Scheme: Implementing n-argument compose using fold

I'm trying to find the "best" implementation of a multi-argument "compose" in Scheme (I know it's a builtin in some implementations, but assume for the moment I am using one that doesn't have this).
For a 2-argument compose function I have this:
(define compose
(lambda (f g)
(lambda x
(f (apply g x)))))
This has the advantage that if the right-most function needs additional arguments, these can still be passed through the combined function. This has the pleasing property that composing the identity function on top of something does not change the function.
For example:
(define identity
(lambda (x) x))
(define list1
(compose identity list))
(define list2
(compose identity list1))
(list2 1 2 3)
> (1 2 3)
Now to do an "n-argument" compose I could do this:
(define compose-n
(lambda args
(foldr compose identity args)))
((compose-n car cdr cdr) '(1 2 3))
> 3
But this no longer preserves that nice "identity" property:
((compose-n identity list) 1 2 3)
> procedure identity: expects 1 argument, given 3: 1 2 3
The problem is that "initial" function used for the foldr command. It has built:
(compose identity (compose list identity))
So... I'm not sure the best way around this. "foldl" would seem to be the natural better alternative, because I want to it start with "identity" on the left not the right...
But a naive implementation:
(define compose-n
(lambda args
(foldl compose identity args)))
which works (have to reverse the order of function applications):
((compose-n cdr cdr car) '(1 2 3))
> 3
doesn't solve the problem because now I end up having to put the identity function on the left!
((compose-n cdr cdr car) '(1 2 3))
> procedure identity: expects 1 argument, given 3: 1 2 3
It's like, I need to use "foldr" but need some different "initial" value than the identity function... or a better identity function? Obviously I'm confused here!
I'd like to implement it without having to write an explicit tail-recursive "loop"... it seems there should be an elegant way to do this, I'm just stuck.
You might want to try this version (uses reduce from SRFI 1):
(define (compose . fns)
(define (make-chain fn chain)
(lambda args
(call-with-values (lambda () (apply fn args)) chain)))
(reduce make-chain values fns))
It's not rocket science: when I posted this on the #scheme IRC channel, Eli noted that this is the standard implementation of compose. :-) (As a bonus, it also worked well with your examples.)
The OP mentioned (in a comment to my answer) that his implementation of Scheme does not have call-with-values. Here's a way to fake it (if you can ensure that the <values> symbol is never otherwise used in your program: you can replace it with (void), (if #f #f), or whatever you like that's not used, and that's supported by your implementation):
(define (values . items)
(cons '<values> items))
(define (call-with-values source sink)
(let ((val (source)))
(if (and (pair? val) (eq? (car val) '<values>))
(apply sink (cdr val))
(sink val))))
What this does is that it fakes a multi-value object with a list that's headed by the <values> symbol. At the call-with-values site, it checks to see if this symbol is there, and if not, it treats it as a single value.
If the leftmost function in your chain can possibly return a multi-value, your calling code has to be prepared to unpack the <values>-headed list. (Of course, if your implementation doesn't have multiple values, this probably won't be of much concern to you.)
The issue here is that you're trying to mix procedures of different arity. You probably want to curry list and then do this:
(((compose-n (curry list) identity) 1) 2 3)
But that's not really very satisfying.
You might consider an n-ary identity function:
(define id-n
(lambda xs xs))
Then you can create a compose procedure specifically for composing n-ary functions:
(define compose-nary
(lambda (f g)
(lambda x
(flatten (f (g x))))))
Composing an arbitrary number of n-ary functions with:
(define compose-n-nary
(lambda args
(foldr compose-nary id-n args)))
Which works:
> ((compose-n-nary id-n list) 1 2 3)
(1 2 3)
EDIT: It helps to think in terms of types. Let's invent a type notation for our purposes. We'll denote the type of pairs as (A . B), and the type of lists as [*], with the convention that [*] is equivalent to (A . [*]) where A is the type of the car of the list (i.e. a list is a pair of an atom and a list). Let's further denote functions as (A => B) meaning "takes an A and returns a B". The => and . both associate to the right, so (A . B . C) equals (A . (B . C)).
Now then... given that, here's the type of list (read :: as "has type"):
list :: (A . B) => (A . B)
And here's identity:
identity :: A => A
There's a difference in kind. list's type is constructed from two elements (i.e. list's type has kind * => * => *) while identity's type is constructed from one type (identity's type has kind * => *).
Composition has this type:
compose :: ((A => B).(C => A)) => C => B
See what happens when you apply compose to list and identity. A unifies with the domain of the list function, so it must be a pair (or the empty list, but we'll gloss over that). C unifies with the domain of the identity function, so it must be an atom. The composition of the two then, must be a function that takes an atom C and yields a list B. This isn't a problem if we only give this function atoms, but if we give it lists, it will choke because it only expects one argument.
Here's how curry helps:
curry :: ((A . B) => C) => A => B => C
Apply curry to list and you can see what happens. The input to list unifies with (A . B). The resulting function takes an atom (the car) and returns a function. That function in turn takes the remainder of the list (the cdr of type B), and finally yields the list.
Importantly, the curried list function is of the same kind as identity, so they can be composed without issue. This works the other way as well. If you create an identity function that takes pairs, it can be composed with the regular list function.
While it would have been nice for the "empty" list to devolve to the identity function, surrendering this appears to result in the following, which isn't too bad:
(define compose-n
(lambda (first . rest)
(foldl compose first rest)))
((compose-n cdr cdr car) '(1 2 3))
((compose-n list identity identity) 1 2 3)

Resources