Let's say I have a macro, inside the macro I have this let:
let[
elements# //stuff//
#newlist (for [e# elements#] (if (number? e#) (**add e# to #newlist**)))
]
Since I am having a really hard time finding proper information on the really simple Clojure stuff, I'm here to ask: what do I need to do to accomplish this task above? I think it should be possible to do this but I don't know the most crucial part!
It looks like you're trying to create a list called newlist which contains all those elements of elements that are numbers. If so, you can just use the filter function like this:
(let
[elements whatever
newlist (filter number? elements)]
do-stuff-with-newlist)
filter takes a predicate function and a list and returns a new list that contains those items for which the predicate returns a true result.
Note that your initial idea of adding to a list inside a for-loop would not work because lists are immutable, so you can not add to them in-place. You could re-assign a variable holding the list inside a for loop (something like (set! my-list (cons e my-list)), but that would not be idiomatic Clojure code. It would also create the list in reverse.
Related
Is there a way in Chicken Scheme to determine at run-time if a variable is currently defined?
(let ((var 1))
(print (is-defined? var)) ; #t
(print (is-defined? var)) ; #f
EDIT: XY problem.
I'm writing a macro that generates code. This generated code must call the macro in mutual recursion - having the macro simply call itself won't work. When the macro is recursively called, I need it to behave differently than when it is called initially. I would use a nested function, but uh....it's a macro.
Rough example:
(defmacro m (nested)
(if nested
BACKQUOTE(print "is nested")
BACKQUOTE(m #t)
(yes, I know scheme doesn't use defmacro, but I'm coming from Common Lisp. Also I can't seem to put backquotes in here without it all going to hell.)
I don't want the INITIAL call of the macro to take an extra argument that only has meaning when called recursively. I want it to know by some other means.
Can I get the generated code to call a macro that is nested within the first macro and doesn't exist at the call site, maybe? For example, generating code that calls (,other-macro) instead of (macro)?
But that shouldn't work, because a macro isn't a first-class object like a function is...
When you write recursive macros I get the impression that you have an macro expansion (m a b ...) that turns into a (m-helper a (b ...)) that might turn into (let (a ...) (m b ...)). That is not directly recursive since you are turning code into code that just happens to contain a macro.
With destructuring-bind you really only need to keep track of two variables. One for car and one for cdr and with an implicit renaming macro the stuff not coming from the form is renamed and thus hygenic:
(define-syntax destructuring-bind
(ir-macro-transformer
(lambda (form inject compare?)
(define (parse-structure structure expression optional? body)
;;actual magic happens here. Returns list structure with a mix of parts from structure as well as introduced variables and globals
)
(match form
[(structure expression) . body ]
`(let ((tmp ,expression))
,(parse-structure structure 'tmp #f body))))))
To check if something from input is the same symbol you use the supplied compare? procedure. eg. (compare? expression '&optional).
There's no way to do that in general, because Scheme is lexically scoped. It doesn't make much sense to ask if a variable is defined if an referencing an undefined variable is an error.
For toplevel/global variables, you can use the symbol-utils egg but it is probably not going to work as you expect, considering that global variables inside modules are also rewritten to be something else.
Perhaps if you can say what you're really trying to do, I can help you with an alternate solution.
What is the difference between values and list or cons in Racket or Scheme? When is it better to use one over the other? For example, what would be the disadvantage if quotient/remainder returns (cons _ _) rather than (values _ _)?
Back in 2002 George Caswell asked that question in comp.lang.scheme.
The ensuing thread is long, but has many insights. The discussion
reveals that opinions are divided.
https://groups.google.com/d/msg/comp.lang.scheme/ruhDvI9utVc/786ztruIUNYJ
My answer back then:
> What are the motivations behind Scheme's multiple return values feature?
> Is it meant to reflect the difference in intent, or is there a
> runtime-practical reason?
I imagine the reason being this.
Let's say that need f is called by g. g needs several values from f.
Without multiple value return, f packs the values in a list (or vector),
which is passed to g. g then immediately unpacks the list.
With multple values, the values are just pushed on the stack. Thus no
packing and unpacking is done.
Whether this should be called an optimization hack or not, is up to you.
--
Jens Axel Søgaard
We don't need no side-effecting We don't need no allocation
We don't need no flow control We don't need no special-nodes
No global variables for execution No dark bit-flipping for debugging
Hey! did you leave the args alone? Hey! did you leave those bits alone?
(Chorus) -- "Another Glitch in the Call", a la Pink Floyd
They are semantically the same in Scheme and Racket. In both you need to know how the return looks like to use it.
values is connected to call-with-values and special forms like let-values are just syntax sugar with this procedure call. The user needs to know the form of the result to use call-with-values to make use of the result. A return is often done on a stack and a call is also on a stack. The only reason to favor values in Scheme would be that there are no overhead between the producer return and the consumer call.
With cons (or list) the user needs to know how the data structure of the return looks like. As with values you can use apply instead of call-with-values to do the same thing. As a replacement for let-values (and more) it's easy to make a destructuring-bind macro.
In Common Lisp it's quite different. You can use values always if you have more information to give and the user can still use it as a normal procedure if she only wants to use the first value. Thus for CL you wouldn't need to supply quotient as a variant since quotient/remainder would work just as well. Only when you use special forms or procedures that take multiple values will the fact that the procedure does return more values work the same way as with Scheme. This makes values a better choice in CL than Scheme since you get away with writing one instead of more procedures.
In CL you can access a hash like this:
(gethash 'key *hash* 't)
; ==> T; NIL
If you don't use the second value returned you don't know if T was the default value or the actual value found. Here you see the second value indicating the key was not found in the hash. Often you don't use that value if you know there are only numbers the default value would already be an indication that the key was not found. In Racket:
(hash-ref hash 'key #t)
; ==> #t
In racket failure-result can be a thunk so you get by, but I bet it would return multiple values instead if values did work like in CL. I assume there is more housekeeping with the CL version and Scheme, being a minimalistic language, perhaps didn't want to give the implementors the extra work.
Edit: Missed Alexis' comment on the same topic before posting this
One oft-overlooked practical advantage of using multiple return values over lists is that Racket's compose "just works" with functions that return multiple values:
(define (hello-goodbye name)
(values (format "Hello ~a! " name)
(format "Goodbye ~a." name)))
(define short-conversation (compose string-append hello-goodbye))
> (short-conversation "John")
"Hello John! Goodbye John."
The function produced by compose will pass the two values returned by hello-goodbye as two arguments to string-append. If you're writing code in a functional style with lots of compositions, this is very handy, and it's much more natural than explicitly passing values around yourself with call-with-values and the like.
It's also related to your programming style. If you use values, then it usually means you want to explicitly return n values. Using cons, list or vector usually means you want to return one value which contains something.
There are always pros/cons. For values: It may use less memory on some implemenentations. The caller need to use let-values or other multiple values specific syntax. (I wish I could use just let like CL.)
For cons or other types: You can use let or lambda to receive the returning value. You need to explicitly deconstruct it to get the value you want using car or other procedures.
Which to use and when? Again depending on your programming style and case by case but if the returning value can't be represented in one object (e.g. quotient and remainder), then it might be better to use values to make the procedure's meaning clearer. If the returning value is one object (e.g. name and age for a person), then it might be better to use cons or other constructor (e.g. record).
I would like to do something like this
(cons '(someword,string->symbol somevarname) (restoflist))
but somevarname is never replaced by its value.
I thought this was possible?
Quote makes literal lists. To make a list dynamically at runtime, you can also use quasiquote and unquote. For your case, it looks something like the following (assume somevarname is either locally or globally bound):
(cons `(someword ,(string->symbol somevarname)) (restoflist))
It is, but because you quoted the expression containing string->symbol, it never got evaluated. I'd try to show the right way to get what you want, but it isn't clear just what that is.
Based on your comment (and ignoring the comma), it seems that you would want:
(cons (list 'someword (string->symbol "somevarname")) restoflist)
I have a let statement in which I would like to dynamically destructure a list. The following is my solution:
symList ;; list of some Strings which will become the vector of Symbols to assign to
valList ;; list of some values, same length as symList
(let [(map read-string symList) valList]
...)
An example value of symList would be ("pt1" "pt2") and an example value of valList would be (1 2)
However, this produces an exception that the first part is an "unsupported binding form". I suspect I am missing something regarding syntax-quoting, or that it's not possible. Any advice would be greatly appreciated.
EDIT: I will only know these values come run time, hence this approach. Secondly, I need to be able to pass the lexical scope later on, hence the use of let.
If symList and valList have the correct value at compilation time, then you could write a macro to do this. If they are only known at runtime, you are going to have to use/write a function to do the destructuring for you and return the result of that destructuring as some data structure.
In the second case, for something simple like this, you can use (zipmap symList valList) to get a map.
(let [valList (map str symList)]
(somefun valList))
The error you are getting is because your let statement was backwards (let [val SOURCE] STUFF)
maybe matchure can give you what you want
Although I've been unable to find a way to dynamically destructure a list, for those of you who are interested in creating values that are lexically instead of dynamically scoped, I found that intern to whatever namespace you need works well.
I am able to delete the element from a list, but I have no idea how to write a function in Scheme to replace all occurrences of an element in a list with another element.
Any help will be appreciated.
A simple version might be designed like this:
(define (replace old-element new-element list)
; if the list is null, just return null
; else if the car of the list is equal to old-element
; run replace on the rest of the list, and cons new-element onto it
; else
; run replace on the rest of the list, and cons the car onto it)
(I left the details up to you, since you gotta learn by doing.)
Remember, in Scheme the most natural way to do things will usually be to assemble a new list piece-by-piece from your old list, not to try to make little changes one at a time to your old list.
Note that you could also use map to do this much more concisely.