Why is my conditional statement being ignored? - scripting

I am trying to write a scheme script for GIMP 2.8, which will resize and rename/copy files. As part of this I would like to change the output file name based on a boolean set in the script.
My conditional however, is being ignored. Here is an excerpt of the script (based on one in this thread):
(define (script-fu-batch-resize globexp globext src)
(define (resize-img n f newx suffix srcdir removetailingunderscore)
(let* ((fname (car f))
;get path, short name + extension (remember to remove source dir to REPLACE with suffix!)
(fullname (car (last (strbreakup fname "\\"))))
(filepath (substring fname 0 (- (string-length fname) (string-length (string-append srcdir fullname)))))
(name0 (car (strbreakup fullname ".")))
(name1 (substring name0 0 (- (string-length name0) 1)) )
(when
(> 1 0)
(
(name0 (name1) )
)
)
(extension (cadr (strbreakup fullname ".")))
(img (car (gimp-file-load 1 fname fname))))
(gimp-image-undo-disable img)
(let*
(
(oldx (car (gimp-image-width img)))
(oldy (car (gimp-image-height img)))
(newy (/ oldy (/ oldx newx)))
)
(gimp-image-scale img newx newy) ;changed for Gimp v2.6
)
(gimp-file-save 1 img (car (gimp-image-get-active-drawable img)) (string-append filepath suffix "\\" name1 "." extension) fname)
(gimp-image-delete img)
)
(if (= n 1) 1 (resize-img (- n 1) (cdr f) newx suffix srcdir removetailingunderscore))
)
(define sourcepattern (string-append globexp src globext))
(define files (file-glob sourcepattern 0)) ;changed for Gimp v2.6
(resize-img (car files) (car (cdr files)) 55 "micro" src 1)
)
I have tried using when and if-else but no matter what no statement inside the conditional block is executed (i.e. if I had the same statement for true and false in the if, neither would be executed). My conditional is being completely ignored but I do not know why. GIMP does not report any syntax errors.
I would suspect I cannot have a conditional inside the define statement, except there is one that works right below it.
Can anyone see what is wrong? Why is my conditional being ignored?

There are several problems with the when expression:
It uses a couple of unnecessary parenthesis
The condition (> 1 0) is always true, therefore it's useless
That's not the way to change the value of a variable, use set!
Move the whole when expression outside the variable definition part of the let*, and make it the first statement in the body of the let*
What you need to do is something like this:
(define (script-fu-batch-resize globexp globext src)
(define (resize-img n f newx suffix srcdir removetailingunderscore)
(let* ((fname (car f))
(fullname (car (last (strbreakup fname "\\"))))
(filepath (substring fname 0 (- (string-length fname) (string-length (string-append srcdir fullname)))))
(name0 (car (strbreakup fullname ".")))
(name1 (substring name0 0 (- (string-length name0) 1)))
(extension (cadr (strbreakup fullname ".")))
(img (car (gimp-file-load 1 fname fname))))
(when (> 1 0)
(set! name0 name1))
<rest of the body>)))

Related

Why can (and must) the variable x appear twice on the left side of the function definition? And what's the meaning?

I'm a green hand with Idris,and get confused with this definition, as I don't understand how it works.
The definitionare as follows.
sameS : (k : Nat)->(j : Nat)->(k = j)->((S k) = (S j))
sameS x x Refl=Refl
Let us start by breaking down the type signature:
sameS : (k : Nat) -> (j : Nat) -> (k = j) -> ((S k) = (S j))
sameS is a function.
sameS take the following arguments:
(k : Nat) a parameter k of type Nat
(j : Nat) a parameter j of type Nat
(k = j) A proof that k and j are equal
sameS returns:
((S k) = (S j)) proof that S k and S j are equal.
Now let us breakdown the definition:
sameS x x Refl = Refl
The type of Refl is a = a.
x is both the first and second argument because both are identical. We know this because the 3rd argument is Refl.
Refl is returned because S x = S x.

Scheme: Why am I getting this error: assertion-violation: argument of wrong type [car (car #{Unspecific})

I believe I have found it to be this function in my program but seems to fail before it even gets to the first line of find_best_candidates function:
(define (count-the-score candList voterList)
(display "Spot 3")
(cond
((null? voterList) 0)
(else
(cond
((or (= (car candList) 0) (= (car voterList) 0)) (+ 0 (count-the-score (cdr candList)(cdr voterList))))
((equal? (car candList) (car voterList)) (+ 1 (count-the-score (cdr candList)(cdr voterList))))
(else (- (count-the-score (cdr candList) (cdr voterList)) 1))
)
)
)
)
(define (find-max myList)
(define sortedList 0)
(display "Spot 4")
(cond
((null? myList) myList)
((null? (cdr myList)) myList)
(else
(set! sortedList (find-max (cdr myList)))
(cond
((null? sortedList) (cdr myList))
((null? (car sortedList)) (car myList))
((null? (car myList)) sortedList)
((= (car (cdr (car myList))) (car (cdr (car sortedList))))
(append sortedList (list (car myList)))
)
((> (car (cdr (car myList))) (car (cdr (car sortedList))))
(list (car myList))
)
(else
sortedList
)
)
(display "Spot 5")
)
)
)
(define (find_best_candidates Voter Candidates)
(display "Spot 2")
(define best 0)
(define score 0)
(define voterScore 0)
(define tempScore 0)
(define max_till 0)
(cond
((null? Candidates) '())
(else
(set! best (find_best_candidates Voter (cdr Candidates)))
(set! score (count-the-score Voter (cdr (car Candidates))))
(set! voterScore (list (car (car Candidates)) score))
(set! tempScore (append best (list voterScore)))
(set! max_till (find-max best))
)
)
(display "Spot 6")
)
(define (fetch-names myList)
(display "Spot 7")
(define prev_ans 0)
(define ll 0)
(cond
((null? (cdr myList)) (list(car (car myList))))
(else
(set! prev_ans (fetch-names (cdr) myList))
(set! ll (append (list (car (car myList))) prev_ans))
ll
)
)
(display "Spot 8")
)
;Main function;
(define (best_candidates Voter Candidates)
(display "Spot 1")
(fetch-names (find_best_candidates Voter Candidates))
(display "Spot END")
)
The data the is being imported is as follows:
(define (test1)
(best_candidates
'( 0 0 0 1 1 1 -1 -1 -1 1)
'((Adams 1 1 1 1 1 1 1 1 1 1)
(Grant -1 -1 -1 -1 -1 -1 -1 -1 -1 -1)
(Polk 1 -1 1 -1 1 -1 1 -1 1 -1)
(Jackson 1 0 1 0 1 0 1 0 1 0)
(Taft 0 -1 0 -1 0 -1 0 -1 0 -1)
(Ford 1 1 1 1 0 0 0 0 0 0)
(Madison 0 0 0 1 -1 0 0 -1 1 1)))
)
; should return (adams ford madison)
The error I end up receiving is:
assertion-violation: argument of wrong type [car]
(car #{Unspecific})
Found my issue. In fetch-names function, I had (set! prev_ans (fetch-names (cdr) myList)) which should have been written as (set! prev_ans (fetch-names (cdr myList))). I misplaced a parenthesis.
The result of the last expression in a function body is the result returned to the callee. Eg.
(define (best_candidates Voter Candidates)
(display "Spot 1")
(fetch-names (find_best_candidates Voter Candidates))
(display "Spot END"))
Will return the implementation defined "undefined value" as required by specification of display. In Racket it looks like #<void> and it is the same object from all of the procedures that are supposed to return an undefined value. Note that it is only undefined in the standard while in an implementation it is very defined so in Racket you can capture it in a variable. set! also returns an undefined value.
Some of your code expects a list, but gets #{Unspecific} which is probably your implementations version of the undefined value. Since it's not a pair car will signal an error.
If you payed for your Scheme course and learned to use display and set! your should ask for your money back. It's as if you already know a C language and try to assimilate Scheme. While you can learn Python that way since it is a C dialect, Scheme is not a C dialect so assimilation mostly works between lisp dialects and not across different language families.

find position of list using Lisp

Without using MEMBER, complete the following definition of a recursive function POS such
that if L is a list and E is an element of L then (POS E L) returns the position of the first
occurrence of E in L, but if L is a list and E is not an element of L then (POS E L) returns 0.
(DEFUN POS (E L)
(COND ((ENDP L) ... )
((EQUAL E (CAR L)) ... )
(T (LET ((X (POS E (CDR L))))
))))
that is my code
(defun pos (E L)
(cond ((endp L) 0)
((equal e (car L)) 1)
(T (let ((x (pos E (cdr L))))
(if (zerop x) x
(+ x 1)))))
im try to test the codition with
(POS '(A B) '((K) (3 R C) A (A B) (K L L) (A B))) => 4
but it give me the answer 4 and throw a error*** -
READ from # #>: an object cannot start with #\ )
I dont know what is #\
(defun pos (el l &optional (acc 1))
(cond ((null l) 0)
((equal el (car l)) acc)
(t (pos el (cdr l) (1+ acc)))))

Why does this 'with' block spoil the totality of this function?

I'm trying to compute parity together with the floor of the half, over natural numbers:
data IsEven : Nat -> Nat -> Type where
Times2 : (n : Nat) -> IsEven (n + n) n
data IsOdd : Nat -> Nat -> Type where
Times2Plus1 : (n : Nat) -> IsOdd (S (n + n)) n
parity : (n : Nat) -> Either (Exists (IsEven n)) (Exists (IsOdd n))
I tried going with the obvious implementation of parity:
parity Z = Left $ Evidence _ $ Times2 0
parity (S Z) = Right $ Evidence _ $ Times2Plus1 0
parity (S (S n)) with (parity n)
parity (S (S (k + k))) | Left (Evidence _ (Times2 k)) =
Left $ rewrite plusSuccRightSucc k k in Evidence _ $ Times2 (S k)
parity (S (S (S ((k + k))))) | Right (Evidence _ (Times2Plus1 k)) =
Right $ rewrite plusSuccRightSucc k k in Evidence _ $ Times2Plus1 (S k)
This typechecks and works as expected. However, if I try to mark parity as total, Idris starts complaining:
parity is possibly not total due to: with block in parity
The only with block I see in parity is the one with the recursive call from parity (S (S n)) to parity n, but clearly that is well-founded, since n is structurally smaller than S (S n).
How do I convince Idris that parity is total?
It looks like a bug to me, because the following solution based on case passes the totality checker:
total
parity : (n : Nat) -> Either (Exists (IsEven n)) (Exists (IsOdd n))
parity Z = Left $ Evidence _ $ Times2 0
parity (S Z) = Right $ Evidence _ $ Times2Plus1 0
parity (S (S k)) =
case (parity k) of
Left (Evidence k (Times2 k)) =>
Left $ rewrite plusSuccRightSucc k k in Evidence _ $ Times2 (S k)
Right (Evidence k (Times2Plus1 k)) =>
Right $ rewrite plusSuccRightSucc k k in Evidence _ $ Times2Plus1 (S k)

Scheme sum-of-squares test

I wrote a sum-of-squares function to test if a number n could be written as the sum of two squares. My code is as follows:
(define (square x) (* x x))
(define (sum-of-squares n)
(define (sum-of-squares-h k)
(cond ((= k n) #f)
((= n (+ (square(floor(sqrt k)))(square(floor(sqrt(- n k))))))#t)
(sum-of-squares-h (+ k 1))))
(sum-of-squares-h 1))
When I test things such as :
(sum-of-squares 1)
(sum-of-squares 2)
(sum-of-squares 4)
(sum-of-squares 8)
(sum-of-squares 10)
My output is:
#f
#t
2
2
#t
Where did I go wrong/ what can I do to fix this? I have seen other ways to go about doing this problem, but if someone could help me by using what I already have that would be great. I am not too familiar with the floor function so I may have used it incorrectly.
EDIT - code with a few tweaks
(define (square x) (* x x))
(define (sum-of-squares n)
(define (sum-of-squares-h k)
(cond ((= k n) #f)
((< n 4) #f)
((= n (+ (square(floor(sqrt k)))(square(floor(sqrt(- n k))))))#t)
(sum-of-squares-h (+ k 1))))
(sum-of-squares-h 1))
You forgot the else part in the last condition:
(define (sum-of-squares n)
(define (sum-of-squares-h k)
(cond ((= k n)
#f)
((= n (+ (square (floor (sqrt k)))
(square (floor (sqrt (- n k))))))
#t)
(else
(sum-of-squares-h (+ k 1)))))
(sum-of-squares-h 1))
Here is my function that finds all the ways that a number n can be written as the sum of squares:
(define (squares n)
(let loop ((x (isqrt n)) (y 0) (zs '()))
(cond ((< x y) zs)
((< (+ (* x x) (* y y)) n) (loop x (+ y 1) zs))
((< n (+ (* x x) (* y y))) (loop (- x 1) y zs))
(else (loop (- x 1) (+ y 1) (cons (list x y) zs))))))
The algorithm is from Dijkstra: x sweeps downward from the square root of n while y sweeps upward from zero; recursion stops when x and y cross. You can read more about it at my blog.