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

Time:07-14

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)))
       ))))

CodePudding user response:

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)")
> 
  • Related