I found a short introduction to Scheme online, and I'm having a bit of trouble with this function:
(define (title-style str)
(let loop ((lc #\space) (i 0) (c (string-ref str 0)))
((if (char=? lc #\space)
(string-set! str i (char-upcase c)))
(if (= (- (string-length str) 1) i)
str
(loop c (+ i 1) (string-ref str (+ i 1)))))))
(display "star wars iv: a new hope")
(display (title-style "star wars iv: a new hope"))
When I try calling it, I get this:
Error: call of non-procedure: #<unspecified>
Call history:
title-style.scm:6: loop
...
title-style.scm:1: g6 <--
That error comes from Chicken Scheme, I am also getting the same results in Chez Scheme.
It converts a string to title case, and from the error messages I got earlier, it does: call of non-procedure: "Star Wars Iv: A New Hope"
I understand what you intend to do, but that's not the right way to structure a conditional expression in Scheme. Also, right before the first if there's a misplaced opening parentheses (which is the one causing the reported error), and you have to advance the recursion in all cases. This should work for non-empty strings:
(define (title-style str)
(let loop ((lc #\space) (i 0) (c (string-ref str 0)))
(cond ((= (- (string-length str) 1) i)
str)
((char=? lc #\space)
(string-set! str i (char-upcase c))
(loop c (+ i 1) (string-ref str (+ i 1))))
(else
(loop c (+ i 1) (string-ref str (+ i 1)))))))
But still, it's not the recommended way to write a solution in Scheme, you're mutating the input string along the way, which is discouraged, and you're thinking in terms of indexes. Besides, you're imposing an extra restriction on your input: that the strings must be mutable, and not all Scheme dialects support this by default.
A functional tail-recursive style is preferred, where we create a new string as output, leaving the original input untouched and leveraging the rich library of list procedures available in the language; this is what I mean:
(define (title-style str)
(let loop ((lc #\space) (lst (string->list str)) (acc '()))
(cond ((null? lst)
(list->string (reverse acc)))
((char=? lc #\space)
(loop (car lst) (cdr lst) (cons (char-upcase (car lst)) acc)))
(else
(loop (car lst) (cdr lst) (cons (car lst) acc))))))
Either way, it works as expected:
(title-style "star wars iv: a new hope")
=> "Star Wars Iv: A New Hope"
Related
I want to write a function, which converts from a "normal" notation like this: "1+4*2-8" to this pre-notation: "+1-*428".
I hope you get the point here.
Important: It must be in Strings.
What I get so far:
(define (converter lst )
(let ((operand1 (car lst))
(operator (car (cdr lst)))
(operand2 (caddr lst)))
(list operator
(converter operand1)
(converter operand2)))
)
(infixLst->prefixLst '(1 + 2 * 3))
I got two problems here.
1) It's for Lists, I need it work for Strings like "1+3" and not '(1+3)
2) It doesn't work so far (even not for Lists), because it give me some errors regarding the "car", e.g: car: expects a pair, given 1
Soo starting with the List -> String change: (I know that (list is unappropriate here. As well as the other list-methods but I didnt got a better idea so far.
(define (infix->prefix str)
(let ((operand1 (car str))
(operator (cadr str))
(operand2 (caddr str)))
(list operator
(infix->prefix operand1)
(infix->prefix operand2)))
)
(infix->prefix "1 + 2")
The normal notation 1+4*2-8 is called infix notation.
If you simply need to use that notation, Racket has a ready module: (require infix), here's a link to its documentation.
If you want to practice writing your own infix parser, the shunting-yard algorithm can do that. It uses a stack to keep track of the operators in the math expression.
If you want to parse math from a string, you need to first split the string into a list of tokens (numbers and operators). Start with a math->tokens procedure that simply returns a list of the tokens without caring about their meaning. There are many ways to write it. Here is one:
(define (math->tokens s)
(let collect-tokens ((i 0) (tokens '()))
(if (= i (string-length s))
(reverse tokens)
(let ((char (string-ref s i)))
(if (not (char-numeric? char))
(let ((operator (string->symbol (string char))))
(collect-tokens (+ i 1) (cons operator tokens)))
(let collect-number ((j (+ i 1)))
(if (and (< j (string-length s))
(char-numeric? (string-ref s j)))
(collect-number (+ j 1))
(let ((number (string->number (substring s i j))))
(collect-tokens j (cons number tokens))))))))))
For example, (math->tokens "+1-*428") returns the list of tokens (+ 1 - * 428). Now you can apply the shunting-yard algorithm to that list.
I am trying to replace a string in the list with another given string, using abstract list functions and lambda only.
The function consumes lst, a list of strings, str, the string you are replacing, and rep, the string you are replacing str with.
Here is an example:
(replace (list "hi" "how" "are" "you") "hi" "bye") -> (list "bye" "how" "are" "you")
Written below is the code that I wrote in recursion and it works.
(define (replace lst str rep)
(cond [(empty? lst) empty]
[(equal? match (first lst))
(cons rep (replace-all (rest lst) match rep))]
[else (cons (first lst) (replace-all (rest lst) match rep))]))
Below that code is what I have tried but I'm not sure how to fix it to make it produce what I want.
(define (replace lst str rep)
(map (lambda (x) (string=? x str)) lst))
Any and all help is appreciated, thanks!
Almost there! you just have to ask, for each string: is this the one I want to replace? then replace it - otherwise leave it untouched:
(define (replace lst str rep)
(map (lambda (x) (if (string=? x str) rep x))
lst))
I'm trying to develop a constructor and selectors for a simple 2x2 matrix but I'm unsure if what I've made is correct. This takes a list with 4 elements and makes a 2x2:
(define matrix2x2
(lambda (list)
(define to-list list) ;returns the list form of this matrix
(define get-place ;returns a place based on input row col
(lambda (row col)
(cond ((and (equal? row 1) (equal? col 1)) (car list))
((and (equal? row 1) (equal? col 2)) (car (cdr list)))
((and (equal? row 2) (equal? col 1)) (car (cdr (cdr list))))
((and (equal? row 2) (equal? col 2)) (car (cdr (cdr (cdr list)))))
(else (display "no such place")))))
(lambda (ret)
(cond ((eq? ret 'get-place) get-place)
((eq? ret 'to-list) to-list)
(else (error "Unknown request" ret))))))
;tests
(define my-matrix (m2x2 '(8 1 2 7)))
((my-matrix 'get-place) 2 2)
(my-matrix 'to-list)
This works... but I'm not sure I'm using selectors properly.
What you've done is the "usual" Scheme way of implementing objects via closures. You could of course go on to define some convenience functions for the selectors:
(define (get-place matrix ix) ((matrix 'get-place) ix)
(define (matrix->list matrix) ...)
I'm not sure I understand what you're asking about the "proper" use of selectors. After all, you already know that it works ...
I am trying to make little human like text searching program in scheme
but this program doesn't work properly time to time
and I can't catch the bug for many hours
could somebody tell me what's wrong with my code?
and is it not that good idea for searching text?
when I search the string "exp"
in the text file which contain nothing but just string "explorer"
error arise
and it tells Found 0
(define (search str)
(set! count 0)
(define len (length str))
;null character calculating
(define data-len (- (length data) 1))
;when string length is less than or equal to data-length
(when (and (not (= 0 len)) (>= data-len len))
(define first-char (first str))
(define last-char (last str))
;is it correct?
(define (exact? str len index)
(if (equal? str (drop (take data (+ index len)) index))
#t
#f))
;check first and last character of string if correct, check whether this string is correct completely, if so, skip to next index
(define (loop [index 0])
(when (> data-len index)
(if (and (equal? first-char (list-ref data index))
(equal? last-char (list-ref data (+ index len -1))))
(when (exact? str len index)
(set! count (+ count 1))
(loop (+ index len)))
(loop (+ index 1)))))
(loop))
(send msg set-label (format "Found : ~a" count)))
I know it's been four years, but I'm nostalgic for my SCHEME class, so I made a thing. (I'd comment instead of answering, but I don't have enough reputation yet. ... And I'm probably about to have less.)
(define (find-pattern pat str); Returns a list of locations of PATturn in STRing.
(define (pattern-found? pat-list str-list); Is the pattern (pat-list) at the beginning of this string (str-list)? Also, they're lists, now.
(cond ((null? pat-list) #t); The base case for the recursion.
((null? str-list) #f); Obvious
((eq? (car pat-list) (car str-list)); First letter matches
(pattern-found? (cdr pat-list) (cdr str-list))); Recurse
(else #f)))
(define (look-for-pattern pat-list str-list counter results-list)
(cond ((null? str-list) results-list); Base case
((pattern-found? pat-list str-list)
(look-for-pattern pat-list
(cdr str-list)
(+ counter 1)
(cons counter results-list)))
(else (look-for-pattern pat-list
(cdr str-list)
(+ counter 1)
results-list))))
(look-for-pattern (string->list pat)
(string->list str)
0
'()))
EDIT: I mean it's been four years since the question, not since SCHEME class. That'd be a little creepy, but then again, who knows how I'll feel in three years?
I wrote this program:
(define find-combination
{lambda (a b)
(if (eq? ((quotient (car a) (car b)) (quotient (car (cdr a)) (car (cdr b)))))
(display "1*v1" + ((quotient (car a) (car b))*"v2"))
(display "0*v1" + "0*v2"))})
(find-combination (list 2 2) (list 2 1))
a and b are two lists. Its give me the next problem: procedure application: expected procedure, given: 1; arguments were: 2.
I didn't get what is the problem. Someone can help me? Thank u.
First of all you have too much brackets after eq? - what you wrote means evaluating (quotient (car a) (car b)) and treating it as a function with argument (quotient (car (cdr a)) (car (cdr b))). The error means that first thing was evaluated to 1 and your interpreter expected it to be a procedure, not an integer. This line should be:
(if (eq? (quotient (car a) (car b)) (quotient (car (cdr a)) (car (cdr b))))
or even:
(if (eq? (quotient (car a) (car b)) (quotient (cadr a) (cadr b)))
Apart from that, lines with display calls are wrong - Scheme doesn't have an infix notation, so + and * are out of place.
First of all you have a set of curly braces in your code(the one before lambda)
Also you have another set of paranthesis around the parameters you passed to eq?
It should be something like this:
(eq? (quotient (car a) (car b)) (quotient (car (cdr a)) (car (cdr b))))
In Scheme and Racket, parentheses change the meaning of things.
1
is a number, but
(1)
is a call to 1 as a function... but 1 is a number, not a function, so this will cause the error you describe.
Your use of curly braces is also a little unsettling to me.