resize image using script-fu gimp - image

I'm trying to prepare a script for auto-resizing image files.
I found this LINK but I cannot figure out how to use it.
Anyone can provide a working script that I can use as a starting point?

The following function resizes the image:
(define (resize-image filename-in filename-out new-width new-height)
(let* ((image (car (gimp-file-load RUN-NONINTERACTIVE filename-in "")))
(drawable (car (gimp-image-active-drawable image)))
)
(gimp-image-scale image new-width new-height)
(gimp-file-save RUN-NONINTERACTIVE image drawable filename-out "")
)
)
Now, resizing all jpg's in a directory:
(define (file-basename filename)
(let*
(
(broken-up (strbreakup filename "."))
(wo-last-r (cdr (reverse broken-up)))
(wo-last (reverse wo-last-r))
(result "")
)
(while wo-last
(set! result (string-append result (car wo-last) ))
(set! wo-last (cdr wo-last))
(if (> (length wo-last) 0) (set! result (string-append result ".")))
)
result
)
)
(define (ex_09 file-pattern new-width new-height )
(let* ( (filelist (cadr (file-glob file-pattern 1))))
(while (not (null? filelist))
(let* ( (cur-file (car filelist)) )
(resize-image
cur-file
(string-append (file-basename cur-file) "_resized.jpg")
100
100
)
(set! filelist (cdr filelist))
)
)
)
)
I think that this is your answer.

The code come from this address.
http://www.adp-gmbh.ch/misc/tools/script_fu/ex_09.html
Out of the box it doesn't work for me.
I made some changes :
In the file_basename.scm file I remove some stuff I didn't get around with.
So the resized files are created in the same directory than the original files :
(define (file-basename filename)
(let*
(
(broken-up (strbreakup filename "."))
(wo-last-r (cdr (reverse broken-up)))
(wo-last (reverse wo-last-r))
(car broken-up)
)
)
In the ex_09.scm file :
I just used the new-width and the new-height variables.
(define (ex_09 file-pattern new-width new-height )
(let* ( (filelist (cadr (file-glob file-pattern 1))))
(while (not (null? filelist))
(let* ( (cur-file (car filelist)) )
(resize-image
cur-file
(string-append (file-basename cur-file) "_resized.jpg")
new-width
new-height
)
(set! filelist (cdr filelist))
)
)
)
)
Hop this helps !
and thank yo René Nyffenegger for the code.
:)

Related

Why do I get "application: not a procedure" with this for loop in Racket?

The following code reads a csv file and based on its content generates a Prolog program:
#!/usr/bin/env racket
#lang racket/base
(define (overwrite-s-to-f fname s); Will create fname and write overwriting the previous content.
(with-output-to-file #:exists 'truncate fname (lambda () (displayln s))))
(define (c-o-a-line-to-f fname s); Will append a string to fname or create it if does not exist. Appends a new line.
(with-output-to-file #:exists 'append fname (lambda () (displayln s))));
(define fname "women.csv")
(define pl-fname "females-by-Racket.pl")
(require racket/file)
(define content (file->lines fname))
(define disc-line (string-append ":-discontiguous(" (string-replace (car content) "Name," "") ").\n"))
(overwrite-s-to-f pl-fname disc-line)
(define list-of-verbs (string-split (string-replace (car content) "Name," "") ","))
(require racket/string racket/system)
(for ((row content));content is a list of strings
(let ((list-of-cs (string-split row ",")))
(when (equal? (car (cdr list-of-cs)) "+")
(displayln row)(let ((cmd (string-append "awesome("(car list-of-cs)").")))(c-o-a-line-to-f pl-fname cmd)(displayln cmd)))
(when (equal? (car (cdr (cdr list-of-cs))) "+")(displayln row)(let ((cmd (string-append "and_intelligent("(car list-of-cs)").")))
(c-o-a-line-to-f pl-fname cmd)(displayln cmd))))); TODO: when for each columns 2-last of women.csv
The content of women.csv:
Name,awesome,and_intelligent,performed_once,extreme1,extreme2,extreme3,extreme4,donkey_thing,dark_eyes,pigmented_face,pigmented_genitals,bleached,had_no_surgeries,has_augmented_breasts
adriana_chechik,+,,,+,?,+,+,,-,,,,,
alysa_gap,+,,,,?,+,+,,-,,,,,
anna_de_ville,+,,,,,+,+,,+,-,+,-,-,
aurora_jolie,+,+,,,,,,,+,+,+,,+,
autumn_falls,,,,,,,,,+,+,-,+,+,
casey_calvert,+,,,,,,,,+,+,+,,,
dahlia_sky,+,,,,,,+,,,,,,,
dominica_lito,+,,,,,,+,,,,,,,
ella_knox,,,,,,,,,+,+,+,,+,
isabella_clark,+,,,,,,+,,,,,,,
jade_kush,,,,,,,,,+,+,,,+,
juelz_ventura,+,,,,,+,,,-,-,,,-,+
kapri_styles,,,,,,,,,+,,+,,,
kristina_milan,,,,,,,,,+,+,,,+,
kylie_sinner,+,+,,,,,,,+,,,,-,
leigh_raven,+,,,,,+,,,+,+,,,,
maserati,,,,,,,,,+,+,,,+,
miosotis,,,,,,,,,+,+,,,+,
scarlett_bloom,,,,,,,,,+,+,+,,-,
sheena_shaw,,,,,,,,,-,,+,,-,
sofia_rose,,,,,,,,,+,,,,+,
teanna_trump,+,,,,,,,,+,,+,,,
veronica_avluv,+,,,,,,+,,,,,,,
yudi_pineda,+,,,,,,,,+,+,,,,
females-by-Racket.pl is to look like so:
:-discontiguous(awesome,and_intelligent,performed_once,extreme1,extreme2,extreme3,extreme4,donkey_thing,dark_eyes,pigmented_face,pigmented_genitals,bleached,had_no_surgeries,has_augmented_breasts).
awesome(adriana_chechik).
awesome(alysa_gap).
awesome(anna_de_ville).
awesome(aurora_jolie).
and_intelligent(aurora_jolie).
awesome(casey_calvert).
awesome(dahlia_sky).
awesome(dominica_lito).
awesome(isabella_clark).
awesome(juelz_ventura).
awesome(kylie_sinner).
and_intelligent(kylie_sinner).
awesome(leigh_raven).
awesome(teanna_trump).
awesome(veronica_avluv).
awesome(yudi_pineda).
but with more predicates (up to n-1 for each woman where n is the number of columns in women.csv)
The names of the columns or the numbers thereof in women.csv are likely to be frequently changed.
That is partly why I wish to avoid manually coding for every when. The other concerns are the sheer amount of the lines to code (15 whens for each column) and the risk of error/typo.
Is it doable to loop through every cell in list-of-cs in such way that it is taken from list-of-verbs?
I've tried this but to no avail (the comment show the error message that I got):
(for ((row content))
(let ((list-of-cs (cdr (string-split row ","))))
(for ((cell list-of-cs))
; application: not a procedure; expected a procedure
; that can be applied to arguments
(set! list-of-verbs (cdr (list-of-verbs)))
(let ((verb (car list-of-verbs)))
(when (equal? cell "+")
(displayln row)
(let ((cmd (string-append verb "(" (car row) ").")))
(c-o-a-line-to-f pl-fname cmd)))
))))
named let is a useful form to be familiar with:
#lang scheme
(define (csv->attributes rows) ;; ListOfString -> ListOfString
;; produce "column-header(row-name)" for "+" entries in csv (see example)
(let ([fields (string-split (car rows) ",")])
(let next-row ([rows (cdr rows)] [result (list)])
(cond
[(null? rows) (reverse result) ]
[else
(let* ([cells (string-split (car rows) ",")]
[name (car cells)])
(let next-cell ([cells (cdr cells)] [fields (cdr fields)] [result result])
(cond
[(null? cells) (next-row (cdr rows) result) ]
[else (next-cell
(cdr cells) (cdr fields)
(if (string=? (car cells) "+")
(cons (string-append (car fields) "(" name ")") result)
result)) ]))) ]))))
(define trio '("Name,fast,slow,sidles"
"Achilles,+,,"
"Tortoise,,+,"
"Crab,,+,+"))
Welcome to DrRacket, version 8.5 [cs].
Language: scheme, with debugging.
> (csv->attributes trio)
("fast(Achilles)" "slow(Tortoise)" "slow(Crab)" "sidles(Crab)")
>

GIMP Scheme Error: ( : 1) eval: unbound variable: strbreakup

I found this wonderful script on github and used it successfully with GIMP on Windows 7. I recently upgraded to Windows 10, and now it will not work. I get the following error:
Error while executing script-fu-batch-smart-resizer:
Error: ( : 1) eval: unbound variable: strbreakup
Here is the code:
; https://github.com/per1234/batch-smart-resize
(define (script-fu-batch-smart-resize sourcePath destinationPath filenameModifier outputType outputQuality maxWidth maxHeight pad padColor . JPEGDCT)
(define (smart-resize fileCount sourceFiles)
(let*
(
(filename (car sourceFiles))
(image (car (gimp-file-load RUN-NONINTERACTIVE filename filename)))
)
(gimp-image-undo-disable image)
;crop to mask if one exists
(if (not (= (car (gimp-layer-get-mask (car (gimp-image-get-active-layer image)))) -1)) (plug-in-autocrop RUN-NONINTERACTIVE image (car (gimp-layer-get-mask (car (gimp-image-get-active-layer image))))))
;image manipulation
(let*
(
;get cropped source image dimensions
(sourceWidth (car (gimp-image-width image)))
(sourceHeight (car (gimp-image-height image)))
;don't resize image to larger than original dimensions
(outputMaxWidth (if (< sourceWidth maxWidth) sourceWidth maxWidth))
(outputMaxHeight (if (< sourceHeight maxHeight) sourceHeight maxHeight))
(outputWidth (if (< (/ sourceWidth sourceHeight) (/ outputMaxWidth outputMaxHeight)) (* (/ outputMaxHeight sourceHeight) sourceWidth) outputMaxWidth))
(outputHeight (if (> (/ sourceWidth sourceHeight) (/ outputMaxWidth outputMaxHeight)) (* (/ outputMaxWidth sourceWidth) sourceHeight) outputMaxHeight))
)
(gimp-image-scale image outputWidth outputHeight) ;scale image to the output dimensions
;pad
(if (= pad TRUE)
(begin
(gimp-image-resize image maxWidth maxHeight (/ (- maxWidth outputWidth) 2) (/ (- maxHeight outputHeight) 2)) ;resize canvas to to maximum dimensions and center the image
;add background layer
(let*
(
(backgroundLayer (car (gimp-layer-new image maxWidth maxHeight RGB-IMAGE "Background Layer" 100 NORMAL-MODE))) ;create background layer
)
(let*
(
(backgroundColor (car (gimp-context-get-background))) ;save the current background color so it can be reset after the padding is finished
)
(gimp-context-set-background padColor) ;set background color to the padColor
(gimp-drawable-fill backgroundLayer 1) ;Fill the background layer with the background color. I have to use 1 instead of FILL-BACKGROUND because GIMP 2.8 uses BACKGROUND-FILL.
(gimp-context-set-background backgroundColor) ;reset the background color to the previous value
)
(gimp-image-insert-layer image backgroundLayer 0 1) ;add background layer to image
)
)
)
)
(gimp-image-flatten image) ;flatten the layers
(let*
(
;format filename - strip source extension(from http://stackoverflow.com/questions/1386293/how-to-parse-out-base-file-name-using-script-fu), add filename modifier and destination path
(outputFilenameNoExtension
(string-append
(string-append destinationPath "/")
(unbreakupstr
(reverse
(cdr
(reverse
(strbreakup
(car
(reverse
(strbreakup filename (if isLinux "/" "\\"))
)
)
"."
)
)
)
)
"."
)
filenameModifier
)
)
)
;save file
(cond
((= outputType 0)
(let*
(
(outputFilename (string-append outputFilenameNoExtension ".png")) ;add the new extension
)
(file-png-save RUN-NONINTERACTIVE image (car (gimp-image-get-active-drawable image)) outputFilename outputFilename FALSE 9 TRUE FALSE FALSE TRUE TRUE)
)
)
((= outputType 1)
(let*
(
(outputFilename (string-append outputFilenameNoExtension ".jpg")) ;add the new extension
)
(file-jpeg-save RUN-NONINTERACTIVE image (car (gimp-image-get-active-drawable image)) outputFilename outputFilename (/ outputQuality 100) 0 TRUE TRUE "" 2 TRUE 0 (if (null? JPEGDCT) 0 (car JPEGDCT)))
)
)
(else
(let*
(
(outputFilename (string-append outputFilenameNoExtension ".gif")) ;add the new extension
)
(gimp-image-convert-indexed image 1 0 256 TRUE TRUE "")
(file-gif-save RUN-NONINTERACTIVE image (car (gimp-image-get-active-drawable image)) outputFilename outputFilename FALSE FALSE 0 0)
)
)
)
)
(gimp-image-delete image)
)
(if (= fileCount 1) 1 (smart-resize (- fileCount 1) (cdr sourceFiles))) ;determine whether to continue the loop
)
;detect OS type(from http://www.gimp.org/tutorials/AutomatedJpgToXcf/)
(define isLinux
(>
(length (strbreakup sourcePath "/" ) ) ;returns the number of pieces the string is broken into
(length (strbreakup sourcePath "\\" ) )
)
)
(define sourceFilesGlob (file-glob (if isLinux (string-append sourcePath "/*.*") (string-append sourcePath "\\*.*")) 0))
(if (pair? (car (cdr sourceFilesGlob))) ;check for valid source folder(if this script is called from another script they may have passed an invalid path and it's much more helpful to return a meaningful error message)
(smart-resize (car sourceFilesGlob) (car (cdr sourceFilesGlob)))
(error (string-append "Invalid Source Folder " sourcePath))
)
)
;dialog
(script-fu-register
"script-fu-batch-smart-resize" ;function name
"batch-smart-resize" ;menu label
"Crop to layer mask, resize within maximum dimensions, and pad to max dimensions(optional)" ;description
"per1234" ;author
"" ;copyright notice
"2015-10-02" ;date created
"" ;image type
SF-DIRNAME "Source Folder" "" ;sourcePath
SF-DIRNAME "Destination Folder" "" ;destinationPath
SF-STRING "Output Filename Modifier(appended)" "" ;filenameModifier
SF-OPTION "Output Type" '("PNG" "JPEG" "GIF") ;outputType
SF-VALUE "Output Quality(JPEG only) 0-100" "90" ;outputQuality
SF-VALUE "Max Width" "1500" ;maxWidth
SF-VALUE "Max Height" "1500" ;maxHeight
SF-TOGGLE "Pad" TRUE ;pad
SF-COLOR "Padding Color" "white" ;padColor
)
(script-fu-menu-register "script-fu-batch-smart-resize"
"<Image>/Tools") ;menu location
I have tried just about everything I could find online, and this is my last resort. Am I missing syntax that was acceptable on the Windows 7 version, that is not so in the Windows 10 version?
Thanks!
strbreakup is defined in script-fu-compat.init in /usr/share/gimp/2.0/scripts (or C:\Program Files\GIMP 2\share\gimp\2.0\scripts for Windows). Is this file present and complete (372 lines in my working version)?
Edit: summary from comments: Gimp didn't look in its standard scripts directory. The directory above should be listed in Edit>Preferences>Folders>Scripts.

chicken scheme ; error while using let inside a function

what is wrong with this code ?
(define (make-node key data )
(list key data 'null 'null ) )
(define (right)(2) )
(define (left) (3) )
;;inserts a key to the tree
;; string x string -> list
(define (insert lst key data )
(if (null? lst )
(make-node key data )
(cond ( [(string>? key (car lst)) (list-set lst 2 (insert lst key data)) ]
[(string<? key (car lst)) (list-set lst 3 (insert lst key data)) ]
[(string=? key (car lst)) (list-set lst 1 data ) ]
))))
(define (list-set lst ix data )
(if (eqv? ix 0 ) ( cons data (cdr lst ) ) ( cons (car lst) (list-set ( cdr lst) ( - ix 1 ) data ))))
( define (newdiction) [
let ( ( [ tree '() ]) [ (msg key data )[ cond ( (eqv? msg 'insert ) [ set! tree (insert tree key data ) ] ) ] ] )
] )
the chicken scheme interpreter spits:
CHICKEN
(c) 2008-2014, The Chicken Team
(c) 2000-2007, Felix L. Winkelmann
Version 4.9.0.1 (stability/4.9.0) (rev 8b3189b)
linux-unix-gnu-x86-64 [ 64bit manyargs dload ptables ]
bootstrapped 2014-06-07
; loading dict.scm ...
Error: during expansion of (let ...) - in `let' - symbol expected: (let (((tree (quote ()))) ((msg key data) (cond ((eqv? msg (quote insert)) (set! tree (insert tree key data)))))))
Call history:
<syntax> (define (list-set lst ix data) (if (eqv? ix 0) (cons data (cdr lst)) (cons (car lst) (list-set (cdr lst...
<syntax> (##core#set! list-set (##core#lambda (lst ix data) (if (eqv? ix 0) (cons data (cdr lst)) (cons (car lst...
<syntax> (##core#lambda (lst ix data) (if (eqv? ix 0) (cons data (cdr lst)) (cons (car lst) (list-set (cdr lst...
<syntax> [list-set] (##core#begin (##core#if (eqv? ix 0) (cons data (cdr lst)) (cons (car lst) (list-set (cdr lst) (- ix...
<syntax> [list-set] (##core#if (eqv? ix 0) (cons data (cdr lst)) (cons (car lst) (list-set (cdr lst) (- ix 1) data)))
<syntax> [list-set] (eqv? ix 0)
<syntax> [list-set] (cons data (cdr lst))
<syntax> [list-set] (cdr lst)
<syntax> [list-set] (cons (car lst) (list-set (cdr lst) (- ix 1) data))
<syntax> [list-set] (car lst)
<syntax> [list-set] (list-set (cdr lst) (- ix 1) data)
<syntax> [list-set] (cdr lst)
<syntax> [list-set] (- ix 1)
<syntax> (define (newdiction) (let (((tree (quote ()))) ((msg key data) (cond ((eqv? msg (quote insert)) (set......
<syntax> (##core#set! newdiction (##core#lambda () (let (((tree (quote ()))) ((msg key data) (cond ((eqv? msg...
<syntax> (##core#lambda () (let (((tree (quote ()))) ((msg key data) (cond ((eqv? msg (quote insert)) (set! t...... <--
This code is suffering from too many parentheses. So Scheme is very flexible and thus you can have code like this:
((som-func som-arg) some-other-arg)
What is happening there? Well. Since (some-func som-arg) is not a special form or macro it has to be an expression that leads to a function so it gets evaluated. Since some-func is not a special form or macro it has to be an expression that leads to a function and thus it evalautes it and some-arg and applies it. The result will be the function to call with the evaluation of some-other-arg as the argument.
I see you use [ ... ] as well as ( ... ). Know that the difference between these are just how they look and the interpretation of them is the same. Thus if you change (+ 1 2) to [+ 1 2] you get 3 both times. No difference. You may use them to indicate some sort of grouping in macros like let, but it makes no difference for the implementation.
If you look at your let:
(let ([(tree '())] ...)
body ...)
So the first variable is (tree '()) with no value.. But (tree '()) isn't a symbol but a list.
(let ([tree '()] ...)
body ...)
Here tree is bound to '(). see?
Now looking at you first cond you have one term. Usually cond has more than two or else a simple if would suffice. The predicate in the one term is:
[(string>? key (car lst)) (list-set lst 2 (insert lst key data))]
Now without the extra ( ... ) around the whole thing the whole code above would become a term instead of just playing a predicate.
But hang on.. Why do you have cond and if. A cond is a if-elseif-else. Isn't there a way to make the whole thing one cond? Yes! This is the same with one cond:
(define (insert lst key data)
(cond
[(null? lst) (make-node key data)]
[(string>? key (car lst)) (list-set lst 2 (insert lst key data))]
[(string<? key (car lst)) (list-set lst 3 (insert lst key data))]
[else (list-set lst 1 data)]))
I noticed also that you check if it's less than, greater than and equal to, but no else (alternative) so I assumed if it weren't less or greater than that it must be equal and thus everything goes in the last term since you now have a complete venn diagram.
You're doing (let (((tree '()) ...) but let expects a list of variable/value pairs. So you'd have to remove one set of parentheses: (let ((tree '())) ...)
In Lisp and Scheme, parentheses have a very specific meaning, you can't just add an extra set of parentheses around an expression without changing its meaning, like you can in many languages.

Scheme Lexical Analyzer

Currently working on a lexical analyzer in Scheme. I'm new to scheme but have a general understanding of what to do. I am following a online tutorial, however I keep getting this error because I'm not using UMASS scheme. What can I do to replace this class (Error: record-parse unbound identifier). Below is my code
#lang racket
(define record_parse
(lambda(noun adjective adverb conjunction prep terminator)
((noun) '(dog cat rat house tree))
((adjective) '(furry fast lazy sneaky))
((adverb) '(quickly silently))
((conjunction) '(and or))
((prep) '(with around up))
((terminator) '(!))))
(define noun '(dog cat rat house tree))
(define adjective '(furry fast lazy sneaky))
(define adverb '(quickly silently))
(define conjunction '(and or))
(define prep '(with around up))
(define terminator '(!))
(define class_parse (record-parse 'parse '(full full)))
(define cons_parse (car class_parse))
(define sel_parse (caddr class_parse))
(define tree_parse (car sel_parse))
(define rest_parse (cadr sel_parse))
(define parse_article
(lambda (list_of_tokens)
(cond
((null? list_of_tokens) #f)
((member? (car list_of_tokens) '(a the))
(cons_parse
(car list_of_tokens)
(cdr list_of_tokens)))
(else #f )
)
)
)
(define (member? x list)
(if (null? list) #f
(if (equal? x (car list)) #t
(member? x (cdr list)))))
(define parse_noun
(lambda (list_of_tokens)
(cond
((null? list_of_tokens) #f)
((member? (car list_of_tokens) noun)
(cons_parse
(car list_of_tokens)
(cdr list_of_tokens)))
(else #f )
)
)
)
(define parse_noun_phrase
(lambda (list_of_tokens)
(let ((p_det (parse_article list_of_tokens)))
(if p_det
(let ( (p_n (parse_noun (rest_parse p_det))))
(if p_n
(cons_parse
(list 'noun_phrase
(tree_parse p_det)
(tree_parse p_n))
(rest_parse p_n)
)
#f)
)
#f)
)
))
(define verb '(loves hates eats chases stalks))
(define parse_verb
(lambda (list_of_tokens)
(cond
((null? list_of_tokens) #f)
((member? (car list_of_tokens) verb)
(cons_parse
(car list_of_tokens)
(cdr list_of_tokens)))
(else #f )
)
)
)
(define parse_verb_phrase
(lambda (list_of_tokens)
(let ((p1 (parse_verb list_of_tokens)))
(if p1
(let ((p2 (parse_noun_phrase (rest_parse p1))))
(if p2
(cons_parse
(list 'verb_phrase
(tree_parse p1)
(tree_parse p2))
(rest_parse p2)
)
#f)
)
#f)
)
))
(define parse_sentence
(lambda (list_of_tokens)
(let ((p1 (parse_noun_phrase list_of_tokens)))
(if p1
(let ((p2 (parse_verb_phrase (rest_parse p1))))
(if p2
(cons_parse
(list 'sentence
(tree_parse p1)
(tree_parse p2))
(rest_parse p2)
)
#f)
)
#f)
)
))
;example of parsing a sentence
;(example
; '(parse_sentence '(the dog chases the cat))
; (cons_parse
; '(sentence (noun_phrase the dog)
; (verb_phrase chases
; (noun_phrase the cat)
; (terminator)))
; '()
; )
; )
(begin
(display "Enter a Sentance in (): ")
(let ((input (read)))
(parse_article (parse_sentence input))))
I am getting the error with the (define class_parse (record-parse 'parse '(full full)))
The procedure you defined is called record_parse, but you're trying to invoke it as record-parse. After that typo is fixed, you'll get a different error: record_parse is defined to receive 6 parameters, but you're passing only two: 'parse and '(full full). And the body of record_parse doesn't make sense, it seems that you tried to implement a case expression, but that's not how it's written in Scheme - at all.
That's only for starters, it looks like there are more errors. You should test each procedure individually until you get the hang of the syntax and before writing more complex behavior that involves using all of the procedures.

Scheme programming I/O and remove

I am doing a scheme project and having some issues with the coding.
For my project we have to keep a class roster(implemented as a list) and be able to perform different operations. I have two questions:
My write roster function opens up the file name passed through but does NOT write the list to the file and Im not sure why? you can find this function in the perform task function , when n = 2.
And my remove function... when I go to test it, I get the error:
;The procedure #[compiled-procedure 13 ("list" #x3) #x14 #x11a2714] has been called with 4 arguments; it requires exactly 2 arguments.
My remove function is called removestu
here is my code:
(define performtask
(lambda (n roster)
(cond ((= n 0) (begin
(display "\n\tResetting roster...\n\n")
(menu '())
))
((= n 1) (begin
(display "\n\tLoad roster from file: ")
(read (open-input-file (read-line)))
(menu roster)
))
((= n 2) (begin
(display "\n\tStore roster to file: ")
(write roster (open-output-file (read-line)))
(menu roster)
))
((= n 3) (begin
(display "\n\tDisplaying roster, sorted by ID:\n")
(printroster (select-sort roster))
(menu roster)
))
((= n 4) (begin
(display "\n\tDisplaying roster, sorted by ID:\n")
(printroster (select-sort-name roster))
(menu roster)
))
((= n 5) (begin
(display "\n\tDisplaying roster, sorted by ID:\n")
(printroster (select-sort-grade roster))
(menu roster)
))
((= n 6) (begin
(display "\n\tEnter student name or ID: ")
(studentinfo roster (read-line))
(menu roster)
))
((= n 7) (begin
(display "\n\tAdd a student to the class roster:\n\n")
(cond ((null? roster) (menu (read-3-items 0 '())))
(else (menu (list (read-3-items 0 '()) roster))))
))
((= n 8) (begin
(display "\n\tEnter student name or ID: ")
(removestu roster (read-line))
(menu roster)
))
((= n 9) (begin
(display "\n\tExiting program...\n\n")
#t
))
(else (begin
(display "\n\tTask no. ")
(display n)
(display " does not exist.\n\n")
(menu roster)
)
)
)
)
)
(define studentinfo
(lambda (lst value)
(cond ((null? lst) (display "\n\tStudent is not found in roster.\n"))
((equal? (car (car lst)) value) (printrecord (car lst)))
((equal? (car (cdr (car lst))) value) (printrecord (car lst)))
(else (studentinfo (cdr lst) value))
)
)
)
(define printroster
(lambda (billy)
(cond ((null? billy) (newline))
(else (begin
(printrecord (car billy))
(printroster (cdr billy))
)
)
)
)
)
(define printrecord
(lambda (lst)
(begin
(display "\tID=")
(display (car lst))
(display ", Name=")
(display (car (cdr lst)))
(display ", Grade=")
(display (car (cdr (cdr lst))))
(newline)
)
)
)
(define select-sort
(lambda (roster)
(cond ((null? roster) '())
(else (cons (smallest roster (car roster)) (select-sort (remove roster (smallest roster (car roster))))))
)
)
)
(define select-sort-name
(lambda (roster)
(cond ((null? roster) '())
(else (cons (smallest-name roster (car roster)) (select-sort (remove roster (smallest-name roster (car ro\
ster))))))
)
)
)
(define select-sort-grade
(lambda (roster)
(cond ((null? roster) '())
(else (cons (smallest-grade roster (car roster)) (select-sort (remove roster (smallest-grade roster (\
car roster))))))
)
)
)
(define smallest
(lambda (roster record)
(cond ((null? roster) record)
((< (car (car roster)) (car record)) (smallest (cdr roster) (car roster)))
(else (smallest (cdr roster) record))
)
)
)
(define smallest-name
(lambda (roster record)
(cond ((null? roster) record)
((< (car (cdr (car roster))) (car (cdr record))) (smallest-name (cdr roster) (car roster)))
(else (smallest-name (cdr roster) record))
)
)
)
(define smallest-grade
(lambda (roster record)
(cond ((null? roster) record)
((< (cdr (cdr (car roster))) (cdr (cdr record))) (smallest-grade (cdr roster) (car roster)))
(else (smallest-grade (cdr roster) record))
)
)
)
(define removestu
(lambda (roster item)
(cond ((null? roster) '())
((equal? item (car roster)) (cdr roster))
(else (cons (car roster) removestu (cdr roster) item))
)
)
)
(define read-3-items
(lambda (n l)
(cond ((= n 0) (begin
(display "\tStudent ID: ")
(read-3-items 1 (list (read)))
))
((= n 1) (begin
(display "\n\tStudent name: ")
(read-3-items 2 (list (car l) (read-line)))
))
((= n 2) (begin
(display "\n\tGrade: ")
(list (car l) (car (cdr l)) (read))
))
)
)
)
(define menu
(lambda (roster)
(begin
(display "\n\tClass roster management system\n")
(display "\t============================\n")
(display "\t MENU\n")
(display "\t============================\n")
(display "\t0. Reset roster\n")
(display "\t1. Load roster from file\n")
(display "\t2. Store roster to file\n")
(display "\t3. Display roster sorted by ID\n")
(display "\t4. Display roster sorted by name\n")
(display "\t5. Display roster sorted by grade\n")
(display "\t6. Display student info\n")
(display "\t7. Add a student to roster\n")
(display "\t8. Remove a student from roster\n")
(display "\t9. Exit\n\n")
(display "\tEnter your choice: ")
(performtask (read) roster)
)
)
)
(write roster (open-output-file (read-line))) seems ok. but you don't close the port you get from open-output-file. Perhaps you should use with-output-to-file instead.
cons is called with 4 arguments (cons (car roster) removestu (cdr roster) item). It takes only two to make a pair!
I noticed that when reading a file you don't use it. The tail call is (menu roster) and the result from (read (open-input-file (read-line))) is read and returned and, since it's not used, deleted.

Resources