Frame 1:26 - What does q unify with? - scheme

We have:
(run* q
(fresh (x)
(==
`(,x)
q)))
In this case `(,x) is a list where the refrence to the variable x isn't quoted.
Does q unifies with a single element list?
Is the result (_0) because q unifies with the fresh variable x (even if it's in a list) or because it doesn't unify with anything at all? Or would in that case the result have been ()?

Does q unify with a single element list?
Yes. (== (list x) q) is the same as (== q (list x)). Both q and x are fresh before the execution of this unification goal (and q does not occur in (list x)). Afterwards, it is recorded in the substitution that the value of q is (list x). No value for x is recorded.
Is the result (_0) because q unifies with the fresh variable x (even if it's in a list) or because it doesn't unify with anything at all? Or would in that case the result have been ()?
No, q does not unify with x, but rather with a list containing x.
When the final value of the whole run* expression is returned, the variables are "reified", replaced with their values. x has no value to be replaced with, so it is printed as _0, inside a list as it happens, which list is the value associated with q.
The value of (run* q ...) is a list of all valid assignments to q, as usual. There is only one such association, for the variable q and the value (list x).
So ( (_0) ) should be printed as the value of the (run* q ...) expression -- a list of one value for q, which is a list containing an uninstantiated x, represented as a value _0.

Related

how to use the if statement in scheme programming?

I just started learning the scheme language and below is a question that I stuck a little bit(Is there anything wrong with my code cuz the error message is kinda weird)
Prompt: Define a procedure over-or-under which takes in a number x and a number y and returns the following:
-1 if x is less than y
0 if x is equal to y
1 if x is greater than y
What I've tried so far is :
(define (over-or-under x y)
(if (< x y)
-1)
(if (= x y)
0)
(if (> x y)
1)
)
The error message is :
scm> (load-all ".")
Traceback (most recent call last):
0 (adder 8)
Error: str is not callable: your-code-here
scm> (over-or-under 5 5)
# Error: expected
# 0
# but got
The syntax of if is:
(if condition expression1 expression2)
and its value is the value of expression1 when the condition is true, otherwise it is the value of expression2.
In your function instead you use:
(if condition expression1)
and this is not allowed. Note, moreover that the three ifs one after the other are executed sequentially and only the value of the last one is actually used, as the value returned by the function call.
A way of solving this problem is using a “cascade” of if:
(define (over-or-under x y)
(if (< x y)
-1
(if (= x y)
0
1)))
Note that the proper alignment make clear the order of execution of the different expressions. If (< x y) is true than the value -1 is the result of the if, but, since it is the last expression of the function, it is also the value of the function call. If this is not true, we execute the “inner” if, checking if x is equal to y, and so on. Note also that in the third case is not necessary to check if x is greater than y, since it is surely true, given that x is not less than y, neither equal to y.
Finally, note that the “cascade” of x is so common that in scheme exists a more syntactically convient way of expressing it with the specific cond expression:
(cond (condition1 expression1)
(condition2 expression2)
...
(else expressionN))
so you could rewrite the function is this way:
(define (over-or-under x y)
(cond ((< x y) -1)
((= x y) 0)
(else 1)))

Reduce Lambda Term to Normal Form

I just learned about lambda calculus and I'm having issues trying to reduce
(λx. (λy. y x) (λz. x z)) (λy. y y)
to its normal form. I get to (λy. y (λy. y y) (λz. (λy. y y) z) then get kind of lost. I don't know where to go from here, or if it's even correct.
(λx. (λy. y x) (λz. x z)) (λy. y y)
As #ymonad notes, one of the y parameters needs to be renamed to avoid capture (conflating different variables that only coincidentally share the same name). Here I rename the latter instance (using α-equivalence):
(λx. (λy. y x) (λz. x z)) (λm. m m)
Next step is to β-reduce. In this expression we can do so in one of two places: we can either reduce the outermost application (λx) or the inner application (λy). I'm going to do the latter, mostly on arbitrary whim / because I thought ahead a little bit and think it will result in shorter intermediate expressions:
(λx. (λz. x z) x) (λm. m m)
Still more β-reduction to do. Again I'm going to choose the inner expression because I can see where this is going, but it doesn't actually matter in this case, I'll get the same final answer regardless:
(λx. x x) (λm. m m)
Side note: these two lambda expressions (which are also known as the "Mockingbird" (as per Raymond Smullyan)) are actually α-equivalent, and the entire expression is the (in)famous Ω-combinator. If we ignore all that however, and apply another β-reduction:
(λm. m m) (λm. m m)
Ah, that's still β-reducible. Or is it? This expression is α-equivalent to the previous. Oh dear, we appear to have found ourselves stuck in an infinite loop, as is always possible in Turing-complete (or should we say Lambda-complete?) languages. One might denote this as our original expression equalling "bottom" (in Haskell parlance), denoted ⊥:
(λx. (λy. y x) (λz. x z)) (λy. y y) = ⊥
Is this a mistake? Well, some good LC theory to know is:
if an expression has a β-normal form, then it will be the same β-normal form no matter what order of reductions was used to reach it, and
if an expression has a β-normal form, then normal order evaluation is guaranteed to find it.
So what is normal order? In short, it is β-reducing the outermost expression at every step. Let's take this expression for another spin!
(λx. (λy. y x) (λz. x z)) (λm. m m)
(λy. y (λm. m m)) (λz. (λm. m m) z)
(λz. (λm. m m) z) (λm. m m)
(λm. m m) (λm. m m)
Darn. Looks like this expression has no normal form – it diverges (doesn't terminate).

Scheme procedure with 2 arguments

Learned to code C, long ago; wanted to try something new and different with Scheme. I am trying to make a procedure that accepts two arguments and returns the greater of the two, e.g.
(define (larger x y)
(if (> x y)
x
(y)))
(larger 1 2)
or,
(define larger
(lambda (x y)
(if (> x y)
x (y))))
(larger 1 2)
I believe both of these are equivalent i.e. if x > y, return x; else, return y.
When I try either of these, I get errors e.g. 2 is not a function or error: cannot call: 2
I've spent a few hours reading over SICP and TSPL, but nothing is jumping out (perhaps I need to use a "list" and reference the two elements via car and cdr?)
Any help appreciated. If I am mis-posting, missed a previous answer to the same question, or am otherwise inappropriate, my apologies.
The reason is that, differently from C and many other languages, in Scheme and all Lisp languages parentheses are an important part of the syntax.
For instance they are used for function call: (f a b c) means apply (call) function f to arguments a, b, and c, while (f) means apply (call) function f (without arguments).
So in your code (y) means apply the number 2 (the current value of y), but 2 is not a function, but a number (as in the error message).
Simply change the code to:
(define (larger x y)
(if (> x y)
x
y))
(larger 1 2)

Limiting variable scope in prolog

I want to declare a list of lists, like so:
%% example 1
Xs = [
[[A],[[A]]],
[[A],[[A],[A]]],
[[A],[[A],[A],[A]]]
].
Here, the symbol A refers to the same variable in each list. Executing maplist(writeln,xs) results in the following output:
[[_G1],[[_G1]]]
[[_G1],[[_G1],[_G1]]]
[[_G1],[[_G1],[_G1],[_G1]]]
I want to use the same symbol A in each list, but for the variable to be distinct for each list, to give the following output:
[[_G1],[[_G1]]]
[[_G2],[[_G2],[_G2]]]
[[_G3],[[_G3],[_G3],[_G3]]]
The only way I make this work is give each list its own unique variable, like so:
%% example 2
Xs = [
[[A1],[[A1]]],
[[A2],[[A2],[A2]]],
[[A3],[[A3],[A3],[A3]]]
].
Is there any Prolog syntax, so that there is no need to number each variable, as per example 2? I tried adding brackets around the lists like so:
Xs = [
([[A],[[A]]]),
([[A],[[A],[A]]]),
([[A],[[A],[A],[A]]])
].
But this gives me the same output as example 1.
Variable names in Prolog have a scope that spans a single clause in a predicate definition, or a query at the top-level. So, this:
?- List = [A, A, A].
means a list with three times the same variable, A. If you put it into a predicate, it would be, say in a file my_lists.pl (I have not nested the lists like you, just to keep it simple):
my_list([A, A]).
my_list([A, A, A]).
my_list([A, A, A, A]).
The As in the three clauses are now not in the same lexical scope, so if you consult this predicate and then collect all possible instantiations of my_list(L) using for example findall/3, you get what you are after:
?- [my_lists].
true.
?- findall(L, my_list(L), Ls).
Ls = [[_G1945, _G1945],
[_G1933, _G1933, _G1933],
[_G1918, _G1918, _G1918, _G1918]].
Is this close to what you are looking for? What is it that you are trying to achieve?
If you want to write out variables and specify a precise name for them, you need the write-option variable_names/1. This answer explains how. Alternatively, you might use the legacy predicate numbervars/3 which unifies distinct variables with a term '$VAR'(N), and then use either writeq/1 or the write-option numbervars(true).
But both methods will not work in the case you indicate. In fact, it was sheer luck that your query
?- Xs = [[[A],[A]],[[A],[A],[A]],[[A],[A],[A],[A]]], maplist(writeln,Xs).
produced the same variables for the different lists. It's even worse, the very same goal writing the very same list, may produce different variable names for different invocations:
p(N) :-
length(_,N),
length(K,1),
writeq(K),
garbage_collect,
writeq(K).
For p(100), SICStus writes [_776][_46], SWI writes [_G517][_G3]. Brief, you caught Prolog on a good day. This is not surprising, for the standard only requires an "implementation dependent" value for a name with a few restrictions: It starts with underscore, and the remaining characters are different for different variables, and the same for the same variable within the same write goal. Here is ISO/IEC 13211-1:1995 on this:
7.10.5 Writing a term
When a term Term is output using write_term/3 (8.14.2)
the action which is taken is defined by the rules below:
a) If Term is a variable, a character sequence repre-
senting that variable is output. The sequence begins
with _ (underscore) and the remaining characters are
implementation dependent. The same character sequence
is used for each occurrence of a particular variable in
Term. A different character sequence is used for each
distinct variable in Term.
The reason for this is that a globally consistent naming of variables would produce a lot of overhead in implementations.
To summarize: If you want to use different variable names for the same variable, then use variable_names/1 with different arguments. If you want the variable to be actually different, then name them differently, or use copy_term/2 accordingly.
You can do it like this:
First, create the desired list structure, with different variables:
?- maplist(length, Lists, [2,3,4]).
Lists = [[X1, X2], [X3, X4, X5], [X6, X7, X8, X9]].
Then, using the following additional definition:
same_element(Ls) :- maplist(=([_]), Ls).
you can unify variables that are in the same sublist to the same term:
?- maplist(same_element, [[X1, X2], [X3, X4, X5], [X6, X7, X8, X9]]).
X1 = X2, X2 = [_G1141],
X3 = X4, X4 = X5, X5 = [_G1149],
X6 = X7, X7 = X8, X8 = X9, X9 = [_G1157].
In combination:
?- maplist(length, Lists, [2,3,4]),
maplist(same_element, Lists),
maplist(writeln, Lists).
yielding:
[[_G1079],[_G1079]]
[[_G1087],[_G1087],[_G1087]]
[[_G1095],[_G1095],[_G1095],[_G1095]]
Now, with the following Emacs definitions:
(defun nice-variables (start end)
(interactive "r")
(goto-char start)
(let ((n 1)
(variables nil)
(m (make-marker)))
(set-marker m end)
(while (and (<= (point) (marker-position m))
(re-search-forward "_G" (marker-position m) t))
(let* ((from (point))
(len (skip-chars-forward "0-9"))
(str (buffer-substring-no-properties from (+ from len)))
(num (assoc str variables)))
(delete-backward-char (+ len 2))
(if num
(insert (format "X%d" (cdr num)))
(setq variables (cons (cons str n) variables))
(insert (format "X%d" n))
(setq n (1+ n)))))))
and M-x nice-variables RET on the region, you get:
[[X1],[X1]]
[[X2],[X2],[X2]]
[[X3],[X3],[X3],[X3]]
This is also what I used on the output of the first query above, to make it more readable.
Thus, you can either generate the structure you want dynamically, by unifying variables you want to be the same, or copy & paste the output above and use it with slight modifications in your program directly.

Simplifying in Prolog

This is a simple mini program I have here that simplifies addition expressions that are queried. I can't seem to figure out how to finish it off. When I query the following:
sim(sum(sum(x,1),5),Val,[x:X]).
My result is Val = X+1+5. I would like it to simplify all the way to X+6.
Here is the code:
sim(Var, Value, Lst) :- member(Var:Value, Lst).
sim(Num, Num, _) :- number(Num).
sim(sum(Left, Right), Value, Lst) :-
sim(Left, LeftVal, Lst),
sim(Right, RightVal, Lst),
so(Value,LeftVal,RightVal).
so(Result, X, Y) :-
number(X),
number(Y), !,
Result is X + Y.
so(Result, X, Y) :- // debugging so(Result,_,Y) :-
Result = X + Y. // Y value write(Y), Result = Y.
What I do know is that my program is trying to simplify X+1 before adding X+1 and 5. When I change the last line of my "so" method to only give Y to Result I get Val = 6. Before that line I write Y to the screen for debugging purposes and it gives me 1 5 because of the recursion. Which means X must be a var? Is there a corner case not here that will allow me to simplify addition all the way down?
What I am noticing is that "so" never adds 1 and 5 because they are never arguments together in the "so" method that checks for X and Y to be numbers. X and 1 are the first arguments, then upon recursion X+1 and 5 are the arguments and it doesn't execute because number(X) fails when X is X+1
Expanding on my comment above: here is an example of an expression simplifier that separates 'symbols' from 'values' using two lists.
Notice how it uses the fact, in parsing and unparsing, that the only operator joining symbols and values is +.

Resources