I have a question about the usage of "map" - Here is the piece of code,
(for-each
(lambda (x) (if (member x sb-id-list) (set! si-exists? #t)))
(append (map thread-id sb1-thread) (map thread-id sb2-thread)))
First of all, I'm sure this code is working correctly - It's taken from the source code of a solver. What I don't understand is that I don't see a "procedure" for the "map" here? Is this some witty usage of map I don't know of? Thanks.
My assumption is that "thread-id" is some sort of procedure.
Like #Kevin mentioned, thread-id is a procedure which takes the sb1-thread parameter
Related
I'm currently doing an assignment for a class where we have to utilize lambdas and locals to redefine functions we've previously defined. I don't really want to just have it written out for me since the issue is something I'm going to face sooner or later.
I don't understand how a local works, and as for a lambda I'm not sure what some of the clauses mean.
Here's an example of a lambda function I made that involved taking only the even numbers from a list and squaring them:
(define (even-squares lon)
(foldr (lambda (x y)
(if (even? x) (cons (sqr x) y)
y)) '() lon))
This worked fine for the problem, but I don't fully get lambda in this situation. I understand that it makes x and y, which are two elements from the list the main focus, and performs an operation regarding them. In this case, an if statement is made where x is tested to be even and then added to a list if it is, or removed otherwise. The function then continues with the y from the first case as the new x and the next element of the list as the new y. Please let me know if this is incorrect in any sense.
What I don't understand in the slightest is why the "else" clause of the if statement is just a y, what does that do?
On the other hand, I am at a complete loss for what a local does. From my little understanding that the old videos my college provides to us gave me, it's a function that produces a function, but I don't understand what it's meant to take in after the definitions clause.
If anyone could provide examples or just explain the concepts I'd greatly appreciate it. Thank you :)
I took the following code from this similar question- the answer has a little bit better argument names:
(define (even-squares-only lon)
(foldr (lambda (element result)
(if (even? element)
(cons (sqr element) result)
result))
'()
lon))
As you can see, the first argument element is an element of the list and the last argument result is an intermediate result/ accumulator.
At the beginning, result is an empty list. In each step, one element from the list is tested. If it meets the condition, it's added to the result squared. If it doesn't, you continue with an unchanged result.
See also documentation for foldl and foldr.
As for the local: if you are familiar with let or letrec, local is similar, just with a little bit different syntax. if documentation entry didn't help you, here is an example:
When rewriting your function, you can decide to remove lambda from foldr and put it somewhere else. So, without any knowledge of local, you can do this:
(define (reducing-fn element result)
(if (even? element)
(cons (sqr element) result)
result))
(define (even-squares-only lon)
(foldr reducing-fn
'()
lon))
reducing-fn is defined globally, so any other function than even-squares-only can use it too.
But you can also define it locally, so it can be used only in the body of local. No other function can use the definition from local and it can also increase readability because you see that reducing-fn "belongs" only to even-squares-only. So, you would rewrite it like this:
(define (even-squares-only lon)
(local [(define (reducing-fn element result)
(if (even? element)
(cons (sqr element) result)
result))]
(foldr reducing-fn
'()
lon)))
Say I've got the following function:
(defun f (v1 v2) ...)
I've got the following code that I'd like to simplify:
(lambda (pair) (apply #'f pair))
The goal here is to create a function that takes a list of two values and calls f with the contents of that list. While this works, it seems a bit verbose. Is there a simpler way to express this?
Maybe:
(lambda(p)(apply #'f p)) ;; 24 bytes
More seriously, Alexandria provides a curry function:
(let ((fun (curry #'apply #'f)))
(funcall fun '(a b)))
Edit: Also, I agree with the sentiment expressed by #Paulo Madeira that your original version is far from being verbose. I would let it as it is, thought, because I think it is in fact easier to debug than using an assert.
(lambda (args) (apply #'f args))
... means "take a list of arguments and apply function F with those arguments". The meaning is straightforward and the function does not make assumptions about what F accepts as arguments. If F is later changed, your closure will still work reliably.
Edit: We don't know what is the context of your code and without more information, your closure looks fishy. If you could describe why you need to pass arguments, we might realize that this approach is not necessarily the most appropriate (or agree that this is in fact a sensible thing to do).
I've been playing with LISP lately, and I want to attempted to optimize a terribly inefficient recursive function by caching it's output so it only runs each combination of parameters once. I want to save the results into hash table, using either (LIST a b) or (CONS a b) as the key. My question is, is that even possible? Documentation I've read would lead me to believe it is, as the document I read defines the key as an 'object', and defines 'object' as something that was constructed with cons. So I gave this a try.
(defparameter *table* (make-hash-table))
(setf (gethash (list 1 2) *table*) 123)
(format t "~S~%" (gethash (list 1 2) *table*))
And it gives me NIL, when I would expect 123. If i replace the (list 1 2) with a cons it still doesn't work, but when I use an plain integer, it works fine.
I'm using GCL 2.6.12
(make-hash-table :test #'equal)
Solutions for caching results of functions has been already implemented for Common Lisp. One is library fare-memoization, the second is function-cache and both are accessible with the Quicklisp. Using the former is as easy as defining normal function:
(define-memo-function your-time-consuming-function (arg)
(code arg))
For reference please check https://github.com/fare/fare-memoization.
Probably the hardest part of learning lisp has been to think in the "lisp way" which is elegant and impressive, but not always easy. I know that recursion is used to solve a lot of problems, and I am working through a book that instead uses apply to solve a lot of problems, which I understand is not as lispy, and also not as portable.
An experienced lisper should be able to help with this logic without knowing specifically what describe-path location and edges refer to. Here is an example in a book I am working through:
(defun describe-paths (location edges)
(apply (function append) (mapcar #'describe-path
(cdr (assoc location edges)))))
I have successfully rewritten this to avoid apply and use recursion instead. It seems to be working:
(defun describe-paths-recursive (location edges)
(labels ((processx-edge (edge)
(if (null edge)
nil
(append (describe-path (first edge))
(processx-edge (rest edge))))))
(processx-edge (cdr (assoc location edges)))))
I would like some more seasoned pairs of eyes on this to advise if there is a more elegant way to translate the apply to recursion, or if I have done something unwise. This code seems decent, but would there been something even more "lispy" ?
(apply (function append) (mapcar #'g ...)) is just mapcan (update: with usual caveats about destructive update and quoted lists, see also this):
(defun describe-paths (location edges)
(mapcan #'describe-path
(cdr (assoc location edges))))
Recursion is good for thinking, for understanding. But actually using it in your code comes with a price.
Your recursive re-write is tail recursive modulo cons; no Lisp has this optimization AFAIK, even though it was first described in 1974, in Lisp.
So what you wrote is good as an executable specification.
But Common Lisp is a practical language. In particular, it has many ways to encode iteration. Remember, iterative processes are our goal; recursive processes are terrible, efficiency-wise. So when we write a code which is syntactically recursive, we still want it to describe an iterative process (such that runs in constant stack space).
Common Lisp, being a practical language, would have us just write the loop out directly. For one,
(defun describe-paths-loop (location edges &aux (res (list 1)) (p res))
(dolist (x (cdr (assoc location edges))
(cdr res)) ; the return form
(setf (cdr p) (describe-path x))
(setf p (last p))))
is guaranteed to work in constant stack space.
update: this destructively concatenates lists returned by describe-path so it should take care not to return lists with the same last cons cell on separate invocations, or this could create circular structure. Alternatively, the call to describe-path could be wrapped in a copy-list call. Of course, if describe-path were to return a list which is already cyclic, last here would go into a loop too.
I saw several opinions about using apply is a bad style. But actually that would be great if somebody will explain me why apply is considered to be bad.
What do you mean using a word "lispy". Common lisp allows to program in any style you want.
If "lispy" means functional programming style, then the first code is written in more functional programming style. A function is passed to a function mapcar and another function is passed to apply and all the job is done by passing the results of one function to another. In you code you don't pass functions as arguments to other functions. But recursion can be considered as functional programming style sign. And code in the book is shorter than yours.
If you don't like apply because of apply determines the argument count in runtime, you can use reduce in this situation (if I understood the data structures correctly):
(Thanks to Joshua Taylor for pointing a huge resource overhead without :from-end t key argument)
(defun describe-paths (location edges)
(reduce #'append (mapcar #'describe-path
(rest (assoc location edges))) :from-end t))
Anyway I'm pretty sure that the purpose of the code in the book is the education reason. It's an example of mapcar and apply that shows how lists are treated as data and code in lisp.
p.s. Actually I figured why apply can be bad (stack is used for function calls).
> (apply #'+ (make-list 500000 :initial-element 1))
*** - Lisp stack overflow. RESET
So as Rainer Joswig told it's lispy to avoid stack overflows. Reduce fix the problem.
> (reduce #'+ (make-list 50000000 :initial-element 1))
50000000
The Lisp way is to use functional, imperative or object-oriented programming (with or without mutable state) to solve a problem, or to invent some other programming as you see fit and express it in macros. Looking for recursion while ignoring other approaches is not the Lisp way; it's the way of the wayward Lisp academic.
The most straightforward way to rewrite the function:
(defun describe-paths (location edges)
(apply (function append) (mapcar #'describe-path
(cdr (assoc location edges)))))
is to use loop. The proper motivation for eliminting apply is that we expect many paths, which could exceed the limit on the number of arguments to a function.
All you are doing with apply is making a big argument list to the append function. We can append any number of lists into a big list with loop like this:
(defun describe-paths (location edges)
(loop for path in (cdr (assoc location edges))
appending (describe-path path))
Presumably, describe-path returns a list, and you want to catenate these together.
The appending clause of loop, which may also be spelled append, gathers appends the value of is argument form into an anonymous list. That list becomes the return value when the loop terminates.
We can use nconcing to improve the performance if we have justification in believing that the lists returned by described-path are freshly allocated on each call.
There's nothing wrong with this question; plenty of questions similar to this are asked in the python category, for example.
But to your question: what you are doing is Good. In fact, it closely resembles, nearly identically, a more general technique Peter Norvig shows in one of his Lisp books, so either you've read that book, or you stumbled upon a good practice on your own. Either way, this is a perfectly acceptable implementation of recursion.
Is there a way to check if a variable exists in Scheme? Even doing things like (if variable) or (null? variable) cause errors because the variable is not defined. Is there some function that returns whether or not a variable exists?
This feature is built into Mit-Scheme.
#lang scheme
(define x "hello world")
(environment-bound? (nearest-repl/environment) 'x)
(environment-bound? (nearest-repl/environment) 'not-x)
Here's an example in Racket:
#lang racket
(define x 1)
(define-namespace-anchor ns)
(define (is-bound? nm)
(define r (gensym))
(not (eq? r (namespace-variable-value nm #t
(lambda () r)
(namespace-anchor->namespace ns)))))
(is-bound? 'x)
(is-bound? 'not-bound-here)
You want to ask questions to the environment. This is not possible with R5RS, and I'm not sure about R6RS. I certainly would like to do that using just the Scheme standard (and this may be part of R7RS -- look for "Environment enquiries" in the list of items they are likely going to work on).
As far as I can tell there are currently only ad-hoc solutions to that so you'll have to read your implementation's documentation.
Chicken supports that with the oblist egg (it lets you obtain a list of all interned symbols), and also with the environments egg, which lets you specificaly ask if one symbol is bound.
Depending on your implementation if may be possible to test this by making a reference to the variable and catching an exception, then checking if it was a not-bound exception, or something similar to that.
According to R6RS, it's a syntax violation to make a call to an unbound variable.
http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-12.html#node_sec_9.1
However, depending on your implementation there should be a way (theoretically, at least) to query the environment and check if a variable is a member. You'd need to do some further reading for that, however.
http://www.r6rs.org/final/html/r6rs-lib/r6rs-lib-Z-H-17.html#node_idx_1268