Can you create local variables without a `let`? - variables

eg1 - using a let
(defun demo1 ()
(let ((a 1)
(b 2))
; these print fine
(print a)
(print b)))
(demo1)
; these get "no value" errors, as expected
(print a)
(print b)
output:
1
2 *** - EVAL: variable A has no value
eg2 - without a let, the variables escape
(this is very surprising for anyone used to more modern scope-rules like eg ruby's)
(defun demo2 ()
(setf a 1)
(setf b 2)
; these print fine
(print a)
(print b))
(demo2)
; these escape, and also print with no error!
(print a)
(print b)
output:
1
2
1
2
how can you make them not escape?
i monkey'd around with setq and defvar
(which were mentioned in the only results i could find by looking for documentation on "local variables")
but no joy at all
eg3 - trying to use a macro
(
this is the practical problem i wanted to solve in the first place --
the syntax of let forces you to use extra layers of parens,
and wrap up the entire function body in the outermost layer,
which just makes it harder to read and write for no reason
(since the overwhelmingly most common use case for let
always includes the entire function body and nothing else),
so i wanted to make a with macro instead
)
(defmacro with (&rest list-of-pairs)
(loop for (name value) in list-of-pairs
do `(setf ,name ,value) ;A
; do (setf name value) ;B
; (i tried both A and B)
))
(defun demo3 ()
(with (a 1)
(b 2))
; this gets a "no value" error when called
(print a)
(print b))
(demo3)
; it never even gets to this point cuz of the above error
(print a)
(print b)
output:
*** - PROGN: variable A has no value
how can you get the variables to escape into the function scope and not beyond?
[
this question asks
can anyone tell me how to define a local variable in lisp other than let?
but none of the answers were helpful to me
]
EDIT-TO-ADD eg4
thinking about the way the loop macro works
(from the point of view of someone calling it without understanding its internals, i mean)...
well, look:
(loop for i from 1 to 5
do (print i))
i don't know yet what the definition of loop looks like,
but it's abstractly something like this, right?:
(defmacro loop ([args somehow,
including the `sexpr`
which goes after the `do` keyword in the macro call])
[other stuff]
do ([sexpr])
[other stuff])
(i'm focusing on the do keyword as an example just because the syntax of the call is relatively simple.)
so what i actually need to do is make my own my-defun macro
and include a with keyword,
right?
something like this:
(defmacro my-defun ([args somehow,
including a `paired-list-of-names-and-values`
to go after a `with` keyword in the macro call])
(let
([paired-list-of-names-and-values])
([function body])))
(my-defun demo4 ()
with (
(a 1)
(b 2)
)
; this should print
(print a)
(print b))
(demo4)
; this should get a "no value" error
(print a)
(print b)
am i on the right track here?
if so, where do i go from here?
like, what are some simple, straight-forward macro definitions i can look at to induce how they work?
or something like that

Simple rule: SETF or SETQ do not create variables. Neither local nor global. They just set variables.
Never set an undefined variable using SETQ and SETF. This is Common Lisp, not Ruby.
It also does not help to create SETF forms with a macro. Why should this make a difference?
Defining local variables
If you look into the Common Lisp standard, there are a zillion constructs which allow to define local variables: DEFUN, DEFMETHOD, LET, LET*, DO, DOTIMES, FLET, LABELS, LAMBDA, DESTRUCTURING-BIND, MULTIPLE-VALUE-BIND, ...
Local variables in functions
If you look at functions, the argument list for functions allows you to define local variables:
required argument
optional argument
keyword argument
auxilliary argument
rest argument
You can define functions with LAMBDA, DEFUN, ...
Example for &optional:
((lambda (a &optional (b 20))
... ; a and b are known here inside the function
)
10) ; we don't need to pass an arg for `b`, optional!
Example for &aux:
((lambda (a &aux (b (+ a 20)))
... ; a and b are known here inside the function
)
10) ; we CAN't pass an arg for `b`, auxiliary!
Variables in LOOP
You don't need to guess what the LOOP macro does, you can ask Lisp to show you - here using LispWorks:
CL-USER 27 > (pprint (macroexpand '(loop for i from 1 to 5
do (print i))))
(BLOCK NIL
(MACROLET ((LOOP-FINISH () '(GO #:|end-loop-82961|)))
(LET ((I 1)
(#:|to-82964| 5)
(#:|by-82965| 1))
(TAGBODY (PROGN (SYSTEM::INTERNAL-IF (OR (> I #:|to-82964|))
(GO #:|end-loop-82961|)))
#:|begin-loop-82960|
NIL
(PRINT I)
(PROGN
(LET ((#:|temp-82966| (+ I #:|by-82965|)))
(SETQ I #:|temp-82966|))
(SYSTEM::INTERNAL-IF (OR (> I #:|to-82964|))
(GO #:|end-loop-82961|)))
(GO #:|begin-loop-82960|)
#:|end-loop-82961|
(RETURN-FROM NIL NIL)))))
As you can see it expands into a form, where the variable i is introduced by a LET. It also expands into a form, which makes use of a goto construct.
As you can see, you can implement a very fancy syntax - like the LOOP syntax - in Lisp. But the implementation of LOOP is large and non-trivial. Nothing for a beginner.

I happen to like how bindings are introduced in Lisp, and I miss it in other languages.
However, I do not attempt to change them to my liking.
Instead, I follow the particular idioms of other languages.
In a comment, you ask:
are you saying that I should be able to use the info you game me to do that, or are you saying that it's just not possible?
In fact, Rainer Joswig is telling you that you should not do that, for the same reason that you do not introduce BEGIN and END macros in C code to replace braces: just work with the existing language instead of directly trying to "fix" it.
By the way, please understand that the existing design of LET is not an accident, and work as expected. The fact that is looks weird to you "from a modern perspective" (see OCaml/F#) does not imply that it is wrong or badly designed. I don't know what you mean with the following comment:
it can properly shadow and unshadow variable definition for parameters passed in to a function
... but I can tell you that it does not make much sense as-is.
Please consult Online Tutorials for programming Common Lisp to have a better view of Lisp before trying to modify it.

Rainer did cover this above, but perhaps not addressed specifically to your example: the &optional parameter for function definition (defun or lambda) seems to be exactly what you are looking for (and indeed is implemented as a macro around let, I believe).
(defun do-stuff (&optional (a 10) (b 20))
(print a)
(print b))
(do-stuff)
10
20
20 <-- return value as last form evaluated in defun
(print a) --> ERROR; it has not escaped.
If you just wanted to try implementing the macro, good on you!

[EDIT:
i just realized that i messed up on the arguement handling,
so my "solution" is broken
if there aren't at least three lists given to my-defun after its parameter list.
i put the (i think) actual working solution at the end.
]
i actually figured this out!
it's not too hard at all,
even for a newb.
(
i mean,
i wouldn't be surprised if horrible things would happen if one actually tried to use it in "real code",
because edge-cases or something,
but it's a working proof-of-concept
)
anyway, here's a definition of the my-defun macro,
working as i described in eg4 in my question:
(
please nobody edit the weird formatting --
i realize it's non-standard,
but it really helps newbs read difficult new stuff.
i mean,
if another newb like me ever reads this,
i think it'll help them significantly.
)
(defmacro my-defun (name params withsymbol withlist &body body)
(cond
((equal withsymbol 'with)
; (print 'withsymbol_set_to_) ;diagnostic
; (print withsymbol) ;diagnostic
; (print 'withlist_set_to_) ;diagnostic
; (print withlist) ;diagnostic
; (print ;diagnostic
`(defun ,name ,params
(let ,withlist
(progn ,#body)
)
)
; ) ;diagnostic
)
(t
; (print 'withsymbol_not_set_to_with_but_) ;diagnostic
; (print withsymbol) ;diagnostic
; (print 'withlist_set_to_) ;diagnostic
; (print withlist) ;diagnostic
; (print ;diagnostic
`(defun ,name ,params
(progn ,withsymbol ,withlist ,#body)
)
; ) ;diagnostic
)
)
)
first test, with a with:
(my-defun demo4 (x)
with (
(a 1)
(b 2)
)
; this prints!
(print a)
(print b)
(print x)
)
(demo4 "hi")
; this correctly gets a "no value" error!
(print a)
(print b)
(print x)
output:
1
2
"hi"
output with diagnostic lines uncommented:
WITHSYMBOL_SET_TO_
WITH
WITHLIST_SET_TO_
((A 1) (B 2))
(DEFUN DEMO4 (X) (LET ((A 1) (B 2)) (PROGN (PRINT A) (PRINT B) (PRINT X))))
1
2
"hi"
second test, with no with:
(so it acts exactly like a normal defun)
(my-defun demo4 (x)
; (this stuff also prints)
(print "i am not the withsymbol")
(print "this is not the withlist")
; this prints!
(print "symbol 'a would have no value")
(print "symbol 'b would have no value")
(print x)
)
(demo4 "hi")
; this correctly gets a "no value" error!
'(print a)
'(print b)
'(print x)
output:
"i am not the withsymbol"
"this is not the withlist"
"symbol 'a would have no value"
"symbol 'b would have no value"
"hi"
output with diagnostic lines uncommented:
WITHSYMBOL_NOT_SET_TO_WITH_BUT_
(PRINT "i am not the withsymbol")
WITHLIST_SET_TO_
(PRINT "this is not the withlist")
(DEFUN DEMO4 (X)
(PROGN (PRINT "i am not the withsymbol") (PRINT "this is not the withlist") (PRINT "symbol 'a would have no value")
(PRINT "symbol 'b would have no value") (PRINT X)))
"i am not the withsymbol"
"this is not the withlist"
"symbol 'a would have no value"
"symbol 'b would have no value"
"hi"
minimally different examples:
using defun with let
and using my-defun with with
(just wanted to eyeball to what extent the result looks worth the trouble xD)
( defun demo (x)
(let (
(a 1)
(b 2)
)
(print a)
(print b)
(print x)
)
)
(my-defun demo (x)
with (
(a 1)
(b 2)
)
(print a)
(print b)
(print x)
)
ACTUALLY WORKING SOLUTION (I HOPE):
(defmacro fun (name params &rest rest)
(let (
(withsymbol (car rest))
(withlist (car (cdr rest)))
(body (cdr (cdr rest)))
)
; (p withsymbol ) ;;debug
; (p withlist ) ;;debug
; (p body ) ;;debug
(cond
((equal withsymbol 'with)
; (print 'BRANCH_A) ;;debug
; (print ;;debug
`(defun ,name ,params
(let* ,withlist
(progn ,#body)
)
)
; ) ;;debug
)
(t
; (print 'BRANCH_B) ;;debug
; (print ;;debug
`(defun ,name ,params
(progn ,#rest)
)
; ) ;;debug
)
)
)
)
;; for debugging
(defmacro p (symbol)
`(format t "~A ~A~%" ',symbol ,symbol)
)
although that was the earliest working version of the code,
so maybe i messed it up without noticing by renaming variables incompletely or something.
the most recent code that i actually just tested is more complicated:
;; used in debug
(defmacro p (symbol)
`(format t "~A ~A~%" ',symbol ,symbol))
(defmacro mac-or-fun (which-one name params rest)
(let (
(withsymbol (car rest))
(withlist (car (cdr rest)))
(body (cdr (cdr rest)))
)
; (p withsymbol ) ;;debug
; (p withlist ) ;;debug
; (p body ) ;;debug
(cond
((equal withsymbol 'with)
; (print 'BRANCH_A) ;;debug
; (print ;;debug
`(,which-one ,name ,params
(let* ,withlist
(progn ,#body)
)
)
; ) ;;debug
)
((equal withsymbol 'omwith)
; (print 'BRANCH_A) ;;debug
; (print ;;debug
`(,which-one ,name ,params
(omlet ,withlist
(progn ,#body)
)
)
; ) ;;debug
)
(t
; (print 'BRANCH_B) ;;debug
; (print ;;debug
`(,which-one ,name ,params
(progn ,#rest)
)
; ) ;;debug
)
)
)
)
(defmacro fun (name params &rest rest)
`(mac-or-fun defun ,name ,params ,rest))
(defmacro mac (name params &rest rest)
`(mac-or-fun defmacro ,name ,params ,rest))
;; for use in tests
(defun ps (&rest stringlist)
(format t "~A~%" (eval `(concatenate 'string ,#stringlist))))
(defparameter *vs-use-count* 0)
(defmacro vs (&rest title)
(setf *vs-use-count* (+ 1 *vs-use-count*))
(ps "
SECTION " (write-to-string *vs-use-count*) " " (write-to-string title) " -"
)
)
;;;tests
(progn
(vs fun works with "with")
(fun f ()
with ((a 1))
(print a)
)
(f)
(vs fun works with "nil")
(fun f ()
()
)
(print(f))
(vs original fun test with "with")
(fun demo4 (x)
with (
(a 1)
(b 2)
)
; this prints!
(print a)
(print b)
(print x)
)
(demo4 "hi")
; these would correctly gets a "no value" error!
'(print a)
'(print b)
'(print x)
(vs original fun test with no "with")
(fun demo4 (x)
; (this stuff also prints)
(print "i am not the withsymbol")
(print "this is not the withlist")
; this prints!
(print "symbol 'a would have no value")
(print "symbol 'b would have no value")
(print x)
)
(demo4 "hi")
; these would correctly gets a "no value" error!
'(print a)
'(print b)
'(print x)
(vs mac works with "with")
(mac m ()
with ((a 1))
(print a)
)
(m)
(vs mac works with "nil")
(mac m ()
()
)
(print(m))
)
;;; more stuff,
;;; leading up to the macro `omlet`,
;;; which is used in `mac-or-fun`
(fun pair-up (l)
with (
(a (car l) )
(b (car (cdr l)) )
(l-past-b (cdr (cdr l)) )
)
(cond
(
(equal 2 (length l))
(list l)
)
(t
(cons (list a b) (pair-up l-past-b))
)
)
)
(fun crack-1 (eggs)
with (
(paired-list (pair-up eggs))
(paired-list (loop for (k v) in paired-list collect `(,k ',v)))
)
paired-list
)
(fun crack-2 (eggs)
with (
(key-name (car eggs))
(value-name (car (cdr eggs)))
(eggs (cdr (cdr eggs)))
(paired-list (pair-up eggs))
(keys-list (loop for pair in paired-list collect (first pair)))
(values-list (loop for pair in paired-list collect (second pair)))
(key-name-keys (list key-name keys-list))
(value-name-values (list value-name values-list))
(paired-list (append paired-list (list key-name-keys value-name-values)))
(paired-list (loop for (k v) in paired-list collect `(,k ',v)))
)
paired-list
)
(fun crack (eggs)
(if
(and
(equal '- (car eggs))
(oddp (length eggs))
)
(crack-2 (cdr eggs))
(crack-1 eggs)
)
)
(mac omlet (eggs &body body)
with ((to-let (crack eggs)))
`(let ,to-let (progn ,#body))
)
(mac lemego (&rest eggs)
with ((to-set (crack eggs)))
(loop for (name value) in to-set
do (eval `(setf ,name ,value))
)
)
;;; more tests
(progn
(vs omlet 1)
(omlet (
x a
y b
z c
)
(print x )
(print y )
(print z )
)
(vs omlet 2)
(omlet (
- names digits
one 1
two 2
three 3
)
(print one )
(print two )
(print three )
(print names )
(print digits )
)
(vs fun with omwith 1)
(fun f ()
omwith (
x a
y b
z c
)
(print x )
(print y )
(print z )
)
(f)
(vs fun with omwith 2)
(fun f ()
omwith (
- names digits
one 1
two 2
three 3
)
(print one )
(print two )
(print three )
(print names )
(print digits )
)
(f)
(vs lemego 1)
(lemego
x a
y b
z c
)
(print x )
(print y )
(print z )
(vs lemego 2)
(lemego
- names digits
one 1
two 2
three 3
)
(print one )
(print two )
(print three )
(print names )
(print digits )
)

Related

Symbol’s value as variable is void: false when run element-of-setp

Following SICP's instruction, I rewrite its intersection-set as:
(defun intersection-set (set1 set2)
(cond ((or (null set1) (null set2)) '())
((element-of-setp (car set1) set2)
(cons (car set1)
(intersection-set (cdr set1) set2)))
(t (intersection-set (cdr set1) set2))))
(defun element-of-setp(x set)
(cond ((null set) false)
((equal x (car set)) t)
(t (element-of-setp x (cdr set)))))
(intersection-set (list 1 2) (list 2 3 4))
Running it reports the following error:
element-of-setp: Symbol’s value as variable is void: false
However, element-of-setp on its own seems to work properly:
#+begin_src emacs-lisp :tangle yes
(defun element-of-setp(x set)
(cond ((null set) false)
((equal x (car set)) t)
(t (element-of-setp x (cdr set)))))
(element-of-setp 1 (list 1 2 3))
#+end_src
#+RESULTS:
: t
What's the problem?
However, element-of-setp on its own seems to work properly:
Unfortunately, the test you used did not cover all the possible cases.
If you try instead:
(element-of-setp 5 (list 1 2 3))
Then the function is going to reach the case where the list is empty, and in that it will evaluate false, which is most likely undefined; as stated in the comment, boolean values in Emacs-Lisp are represented by nil and non-nil values (atoms).

Custom Scheme indexing function returns list-external value

I'm a newbie to scheme programming and I was writing small codes when I encountered the following issue and couldn't reason about it satisfactorily.
(define (at_i lst i)
(if (eq? i 0)
(car lst)
(at_i (cdr lst)
(- i 1) )))
Evaluation of (at_i '(1 2 3 4) 0) returns 1.
Now lets define same procedure with a lambda syntax.
(define (at_i lst i)
(lambda (vec x)
(if (eq? x 0)
(car vec)
(at_i (cdr vec)
(- x 1) )))
lst i)
But now Evaluation of (at_i '(1 2 3 4) 0) returns 0, which is not in the list and in general, it returns element at index-1.
I don't understand why this is happening.
Note: I just realized its not returning element at index - 1 but the index itself. The reason for this has been well explained below by #Renzo. Thanks!
First, you should indent properly the code if you intend to learn the language, since code indentation is very important to understand programs in Scheme and Lisp-like languages.
For instance, your function correctly indented is:
(define (at_i lst i)
(lambda (vec x)
(if (eq? x 0)
(car vec)
(at_i (cdr vec) (- x 1))))
lst
i)
From this you can see that you are defining the function at_i exactly as before in terms of a function with two parameters (lst and i), and whose body is constitued by three expressions: the first lambda (vec x) ... (- x 1)))), which is an (anonymous) function (lambda) which is not called or applied, the second, which is the first parameter lst, and finally the third which is the second parameter i. So, when the function at_i is called with two arguments, the result is the evaluation of the three expressions in sequence, the first two values are discarded (the function and the value of lst), and the result is the value of the second parameter i. This is reason for which the result of (at_i '(1 2 3 4) 0) is 0, since it is the value of i.
A proper redefinition of the function in lambda form would be the following, for instance:
(define at_i
(lambda (vec x)
(if (eq? x 0)
(car vec)
(at_i (cdr vec) (- x 1)))))
(at_i '(1 2 3 4) 0) ;; => 1
in which you can see that the name at_i, through the define, is associated to a two parameter function which calculates correctly the result.
eq? is memory object equality. Only some Scheme implementations interpret (eq? 5 5) as #t. Use = for numbers, eqv? for values, and equal? for collections.
(define (index i xs) ; `index` is a partial function,
(if (= i 0) ; `i` may go out of range
(car xs)
(index (- i 1) ; Tail recursion
(cdr xs) )))
Your second function returns the index because you missed parenthesis around the lambda's application. It should be
(define (index i xs)
((lambda (i' xs')
(if (= i' 0)
(car xs')
(index (- i' 1) ; Not tail-recursive
(cdr xs') )))
i xs))
But this is verbose and differs semantically from the first formulation.
You say you are defining the "same procedure with a lambda syntax", but you are not. That would be (define at_i (lambda lst i) ...). Instead, you are effectively saying (define (at_i lst i) 1 2 3), and that is 3, of course.
In your particular case, you defined the procedure at_i to return (lambda (vec x) ...), lst and i. Now, if you call (at_i '(1 2 3 4) 0), the procedure will return 0, since that is the value of i at this point.

(assoc element alist) get all the entities autolisp

I've googled for it for a while but I didn't find the solution.
I've this list:
((-1 . <Nome entità: 7ff5ff905910>) (0 . "DICTIONARY") (5 . "1F9") (102 . "{ACAD_REACTORS") (330 . <Nome entità: 7ff5ff9038c0>) (102 . "}") (330 . <Nome entità: 7ff5ff9038c0>) (100 . "AcDbDictionary") (280 . 0) (281 . 1) (3 . "1") (350 . <Nome entità: 7ff5ff9933c0>) (3 . "2") (350 . <Nome entità: 7ff5ff9fa0d0>) (3 . "3") (350 . <Nome entità: 7ff5ff9fa410>))
I want to get all the entities with dxf code 350.
With that instruction I can get only the fist one.
(assoc 350 list)
How to get all the associations?
Thanks, Dennis
There are various ways to achieve this - here are a few examples:
(defun mAssoc1 ( key lst / rtn )
(foreach x lst
(if (= key (car x))
(setq rtn (cons (cdr x) rtn))
)
)
(reverse rtn)
)
(defun mAssoc2 ( key lst )
(apply 'append
(mapcar
(function
(lambda ( x ) (if (= key (car x)) (list (cdr x))))
)
lst
)
)
)
(defun mAssoc3 ( key lst )
(mapcar 'cdr
(vl-remove-if-not
(function (lambda ( x ) (= key (car x))))
lst
)
)
)
(defun mAssoc4 ( key lst / item )
(if (setq item (assoc key lst))
(cons (cdr item) (mAssoc4 key (cdr (member item lst))))
)
)
(defun mAssoc5 ( key lst / item rtn )
(while (setq item (assoc key lst))
(setq rtn (cons (cdr item) rtn) lst (cdr (member item lst)))
)
(reverse rtn)
)
(defun mAssoc6 ( key lst )
(mapcar 'cdr (acet-list-m-assoc key lst))
)
(defun mAssoc7 ( key lst )
(if lst
(if (= key (caar lst))
(cons (cdar lst) (mAssoc7 key (cdr lst)))
(mAssoc7 key (cdr lst))
)
)
)
Here is a quick performance comparison for the above functions:
;;; Benchmarking: Elapsed milliseconds / relative speed for 32768 iteration(s):
;;;
;;; (MASSOC4 2 L).....1482 / 1.25 <fastest>
;;; (MASSOC5 2 L).....1482 / 1.25
;;; (MASSOC6 2 L).....1498 / 1.24
;;; (MASSOC3 2 L).....1638 / 1.13
;;; (MASSOC7 2 L).....1747 / 1.06
;;; (MASSOC1 2 L).....1748 / 1.06
;;; (MASSOC2 2 L).....1856 / 1 <slowest>
assoc returns only first one, so You need to loop by all after find one as long as none is found (assoc returns nil). You should try such code:
(defun DXF:Dump (EntDef code / out)
(while (setq values(assoc code EntDef))
(setq out (append out (list (cdr values))))
(setq EntDef(cdr(member values EntDef)))
)
out
)
; (setq dxfs (entget (car (entsel))))
; (DXF:Dump dxfs 350)

Racket: Map with keys/iterating?

I've got some function func and want to apply it on a list lst, so I used map but I need to have the first and last element of the list evaluated with some other function func2.
So basically I want this:
(map (lambda (x)
(cond [(isBeginningOfList? lst) (func2 x)]
[(isEndOfList? lst) (func2 x)]
[else (func x)]))
lst)
Obviously this doesn't work.
How can I achieve this functionality?
Can I somehow get a key of each list entry? Like lambda(key,val) and then compare (equal? key 0) / (equal? key (length lst))?
There's for/list with in-indexed and that does what you describe:
(define (f lst f1 f2)
(define last (sub1 (length lst)))
(for/list (((e i) (in-indexed lst)))
(if (< 0 i last)
(f1 e)
(f2 e))))
then
> (f '(1 2 3 4 5) sub1 add1)
'(2 1 2 3 6)
You can use a map on all the elements except the first and the last one and treat those two separately. In this way you avoid those comparisons which you would do for every element.
(define special-map
(λ (lst f1 f2)
(append (list (f1 (car lst)))
(map f2 (drop-right (cdr lst) 1))
(list (f1 (last lst))))))
Example
Let's try to increment the first and the last elements and decrement all the others.
> (special-map '(1 2 3 4 5) add1 sub1)
'(2 1 2 3 6)
Later edit
I changed (take (cdr lst) (- (length lst) 2)) with (drop-right (cdr lst) 1).

application: not a procedure racket

i am new to racket. i am trying create a list from the input of the user and when the value 0 is entred the first three elements are printed.
here is the code:
#lang racket
(define lst '())
(define (add)
(define n(read))
(if (= n 0)
;then
(
list (car lst) (cadr lst) (caddr lst)
)
;else
(
(set! lst (append lst (list n)))
(add)
)
)
)
(add)
i tested the program with the values 1 2 3 4 5 0
but i keep getting this error:
application: not a procedure;
expected a procedure that can be applied to arguments
given: #<void>
arguments...:
'(1 2 3)
can anyone help me figure out what's wrong.
If you have more than one expression in the "then" or "else" parts, you must enclose them inside a begin, because a pair of () in Scheme are used for function application - that explains the error you're getting. Try this:
(define (add)
(define n (read))
(if (= n 0)
; then
(list (car lst) (cadr lst) (caddr lst))
; else
(begin
(set! lst (append lst (list n)))
(add))))
I had a similar problem, in a function i called a parameter with the same name of a structure, so, trying to create an instance of that structure i got the same error.
example:
> (struct example (param1 param2) #:transparent)
> (define e (example 1 2))
> e
(example 1 2)
> (define (fn e)
(example (example-param1 e) 0))
> (fn e)
(example 1 0)
> (define (fn example)
(example (example-param1 example) 0))
> (fn e)
application: not a procedure;
expected a procedure that can be applied to arguments
given: (example 1 2)
arguments...:
I hope this helps
Your code have a few problems, for example it will fail if you enter less than 3 elements. Also, it is not considered good style to define variables at the module level.
I'd suggest the following:
(define (add)
(define (sub cnt lst)
(define n (read))
(if (= n 0)
(reverse lst)
(if (< cnt 3)
(sub (add1 cnt) (cons n lst))
(sub cnt lst))))
(sub 0 '()))