counter in if statement - if-statement

I prepared a few lines in Scheme and I am new to Scheme. Please post your comments about my code below:
(define new3
(lambda(y)
(define points 444)
(define add3 (lambda (x)(+ x 3)))
(display "--")
(display points)
(if (and (= 1 1)(= 2 2))(add3 points))
(display "--")
(display points)
(list points points)
))
(new3 7)
OUTPUT
--444--444(444 444)
I wonder why the "points" after the "if" are not equal to "447"?
Thank you.

That's because you didn't update points in-place. You computed 477 with (add3 points), but without storing that result anywhere.

Related

Draftsight LISP, problems building a list of x coordinates with the (cons ) function

I am trying to loop through some rectangles and put the x and y coordinates separately in a list. However the list I am trying to fill looks terrible, the code:
(setq sspnls (ssget '((0 . "LWPOLYLINE"))))
(while (= 1 (getvar 'cmdactive))
(command pause)
)
(setq pnlslength (sslength sspnls))
(setq xlist (list))
(setq ylist (list))
(setq pnlname(ssname sspnls 0))
(setq sssort (ssadd))
(setq tllr 0)
(while (< tllr pnlslength)
(setq pnlname(ssname sspnls tllr))
(Command "hatch" "S" pnlname "")
(setq xs (cadr (assoc 10 (entget pnlname)))); y cordinate
(setq ys (caddr (assoc 10 (entget pnlname)))); x cordinate
(setq xlist (cons xlist xs))
(setq ylist (cons ylist ys))
(setq tllr (+ tllr 1))
);while end
The xlist or y list comes out like:
((((nil . 12057.63625954) . 12057.63625954) . 10345.63625954) . 10345.63625954)
I need it to look like:
(12057.63625954 12057.63625954 10345.63625954 10345.63625954)
What am I doing wrong? Please note I am using Draftsight, I also used the append function but the append function does not work at all?
Thanks a lot for your help!
The main issue is that you are using the cons function to create a dotted pair of the list and the X & Y coordinate values, instead of pushing the X & Y coordinate values onto the head of the existing list.
For example, your code is doing this:
_$ (cons '(1 2 3 4) 5)
((1 2 3 4) . 5)
Instead of this:
_$ (cons 5 '(1 2 3 4))
(5 1 2 3 4)
In general, your code could be reduced to the following:
(if (setq sel (ssget '((0 . "LWPOLYLINE"))))
(repeat (setq idx (sslength sel))
(setq idx (1- idx)
ent (ssname sel idx)
enx (entget ent)
xls (cons (cadr (assoc 10 enx)) xls)
yls (cons (caddr (assoc 10 enx)) yls)
)
(command "_.hatch" "_S" ent "")
)
)
Note also that you are only retrieving the coordinates of the first polyline vertex - I'm unsure whether or not this is intentional.
Was a bit hesitant to try at first but CMS IntelliCAD turned out to be a good alternative for me. The free trial worked immediately, which was good to try it out before paying for it. All the features it offers are user-friendly and easy to work with, which was another win for me. Good job.

Updating a list without using set! - Scheme

I've a problem about keeping a list in the memory without using set!
I have an initial empty list defined,
(define database (list))
then I have this procedure which checks if the password is correct and adds the pair to the list.
(define (set-pass l)
(if (pair? l)
(if (check-pass (second (last l)))
(add-to-list l)
"password does not meet policy requirements"
)
"invalid input"
)
)
And a add-to-list procedure:
(define (add-to-list l)
;(append database l)
;implement this.
)
Problem is, I have to call this procedure multiple times:
(set-pass '('john '(X p c F z C b Y h 1 2 3 4 : :)))
(set-pass '('john '(X p c F z C b Y : 1 2 3 4 : :)))
(set-pass '('john '(X p c F z C b : : 1 2 3 4 : :)))
I implemented the procedure add-to-list like I'm calling set-pass once (with append as shown above), but I couldn't find a way to implement if I call it multiple times. I tried a few things mentioned here, here and here. But I couldn't achieve what I wanted. So how can I do this?
It's possible to do this functionally by having the database as a variable:
(let loop ((input (read-line)) (database '()))
(display (format "inserting ~a\n" input))
(loop (read-line)
(cons input database)))
The other features (removing etc) work the same way you as recur with the altered structure according the operation.
You can also update a list with set-cdr!. While set! mutates what a symbol points to, set-cdr! mutates the cdr of a pair. Since it needs to be a pair you need to have the first element be some dummy data:
(define database (list "head"))
(define (add element)
(let ((tmp (cdr database)))
(set-cdr! database (cons element tmp))))
(define (delete element)
(let loop ((prev database) (cur (cdr database)))
(cond ((null? cur) #f)
((equal? (car cur) element)
(set-cdr! prev (cdr cur)))
(else (loop cur (cdr cur))))))
(define (get)
(cdr database))
(add 1)
(add 2)
(add 3)
(get) ; ==> (3 2 1)
(delete 2)
(get) ; ==> (3 1)
The second you allow mutation the cat is out of the bag and all mutation is available. Eg. you can make a mutable object with closures if set! is provided and you can get mutable bindings with boxes if set-car!/set-cdr! is provided.

How would I store a value into read for Scheme? Or is that not even possible?

(define (getFirstFew lst)
(cond
((= (read) 0) '()) ;returns nothing
(else(cons (car lst)(getFirstFew (cdr lst)(- (read) 1))))))
That is my code above. So i'm trying to write a procedure that will get the first x elements (user gets to choose what x gets to be) from a list. For example, input 4 with (getFirstFew '(1 6 2 4 5)) will result in '(1 6 2 4).
My current problem with this is that with using read two times, it gets called twice and then breaks the program. Is there a way for me to store whatever the user inputs into a variable and then use that variable throughout the program? Or is there another solution to this problem?
Notice that you have to perform the read only once, and store the value for future reference. Normally we'd use a let for this, but given that we also have to iterate over the list and decrement x on each iteration, a named let will be more appropriate. Try this:
(define (getFirstFew lst)
(let loop ((lst lst) (x (read)))
(if (= x 0)
'()
(cons (car lst)
(loop (cdr lst) (- x 1))))))
It works as expected:
(getFirstFew '(1 6 2 4 5))
> 4
=> '(1 6 2 4)

Using literal when number expected in Racket

I'm trying to use this:
(vector-set! (vector-ref array (car xy)) (cdr xy) step_count)
where xy is a list like '(0 0) passed in as a parameter.
But I get this error:
vector-set!: contract violation
expected: exact-nonnegative-integer?
given: '(0)
argument position: 2nd
other arguments...:
'#(0 0 0 0 0)
1
There is a problem with (cdr xy), I think I need to turn '(0) into 0 but I can't find a mechanism in Racket that can do that.
I know a line like this:
(vector-set! (vector-ref array (sub1 (car xy))) (sub1 (cdr xy)) (read))
works when you form xy with:
(define xy (cons (read) (read)))
Can someone point me in the right direction?
Thanks for reading.
When you use cdr on a list, it means "the rest of the list". The rest of a list is always a list, not a single element of a list.
If you want the second element of the list xy, then you need to use cadr.
(You could also use second.)
(define xy (list 1 2 3))
(cdr xy) ; '(2 3)
(cadr xy) ; 2
(second xy) ; 2

Scheme language: merge two numbers

How can I merge two integers from a list into one? (in Scheme)
Example:
'(11 223) -> 11223
Assuming that the list has exactly two elements, and that both are numbers:
(define (merge-numbers lst)
(let ((1st (number->string (first lst)))
(2nd (number->string (second lst))))
(string->number (string-append 1st 2nd))))
It works as expected:
(merge-numbers '(11 223))
> 11223
Alternatively, without using a let:
(define (merge-numbers lst)
(string->number
(string-append
(number->string (first lst))
(number->string (second lst)))))
This is my original answer from Jan 25 '12 at 3:05. It only handles the given test. It was a mindless answer, sorry.
(define (merge ls) 11223)
(merge '(11 223))
This is my new answer that handles all cases when passed a list of numbers. Thank you blubberdiblub for the pointer!
; list of zero or more strings -> string
(define (merge-numbers ns)
(if (null? ns) ""
(let ((first-n (number->string (car ns)))
(rest-ns (cdr ns)))
(string-append first-n (merge-numbers rest-ns)))))
(merge-numbers '(11 223))
(merge-numbers '())
(merge-numbers '(1))
(merge-numbers '(1 2))
(merge-numbers '(1 2 3))
(merge-numbers '(1 2 3 4))
(merge-numbers '(1 2 3 4 5))
"11223"
""
"1"
"12"
"123"
"1234"
"12345"
Since the original question probably meant that the result should be a number, and this results in a string, then string->number needs to be used to get the final answer. Thank you again blubberdiblub for an explanation of what the poster probably meant, I had missed it.
There are many ways to write this procedure, depending on what you plan for it. For example, if the list might contain more than two numbers (in the future?) then you can write it as follows:
(define merge-numbers
(lambda (s)
(string->number
(apply string-append
(map number->string s)))))
So now you can type:
> (merge-numbers '(4 9 66 33 555 1))
4966335551
If there's a real reason why you want the number two, then I think the use of the procedure format would be more readable:
(define merge-two-numbers
(lambda (s)
(string->number
(format "~a~a"
(car s)
(cadr s)))))
etc.