DrRacket Locals and Lambdas - racket

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)))

Related

Find max in lisp

I am trying to do Recursive method to find max value in list.
Can anyone explain where I made the mistake on this code and how to approach it next time.
(defun f3 (i)
(setq x (cond (> (car (I)) (cdr (car (I))))
(f3 (cdr (I)))))
)
(f3 '(33 11 44 2) )
also I tried this following method and didn't work:
(defun f3 (i)
(cond ((null I )nil )
(setq x (car (i))
(f3(cdr (i)))
(return-from max x)
)
Thanks a lot for any help. I am coming from java if that helps.
If you're working in Common Lisp, then you do this:
(defun max-item (list)
(loop for item in list
maximizing item))
That's it. The maximizing item clause of loop determines the highest item value seen, and implicitly establishes that as the result value of loop when it terminates.
Note that if list is empty, then this returns nil. If you want some other behavior, you have to work that in:
(if list
(loop for item in list
maximizing item))
(... handle empty here ...))
If the number of elements in the list is known to be small, below your Lisp implementation's limit on the number of arguments that can be passed to a function, you can simply apply the list to the max function:
(defun max-item (list)
(apply #'max list))
If list is empty, then max is misused: it requires one or more arguments. An error condition will likely be signaled. If that doesn't work in your situation, you need to add code to supply the desired behavior.
If the list is expected to be large, so that this approach is to be avoided, you can use reduce, treating max as a binary function:
(defun max-item (list)
(reduce #'max list))
Same remarks regarding empty list. These expressions are so small, many programmers will avoid writing a function and just use them directly.
Regarding recursion, you wouldn't use recursion to solve this problem in production code, only as a homework exercise for learning about recursion.
You are trying to compute the maximum value of a list, so please name your function maximum and your parameter list, not f3 or i. You can't name the function max without having to consider how to avoid shadowing the standard max function, so it is best for now to ignore package issues and use a different name.
There is a corner case to consider when the list is empty, as there is no meaningful value to return. You have to decide if you return nil or signal an error, for example.
The skeleton is thus:
(defun maximum (list)
(if (null list)
...
...))
Notice how closing parentheses are never preceded by spaces (or newlines), and opening parentheses are never followed by spaces (or newlines). Please note also that indentation increases with the current depth . This is the basic rules for Lisp formatting, please try following them for other developers.
(setq x <value>)
You are assigning an unknown place x, you should instead bind a fresh variable if you want to have a temporary variable, something like:
(let ((x <value>))
<body>)
With the above expression, x is bound to <value> inside <body> (one or more expressions), and only there.
(car (i))
Unlike in Java, parentheses are not used to group expressions for readability or to force some evaluation order, in Lisp they enclose compound forms. Here above, in a normal evaluation context (not a macro or binding), (i) means call function i, and this function is unrelated to your local variable i (just like in Java, where you can write int f = f(2) with f denoting both a variable and a method).
If you want to take the car of i, write (car i).
You seem to be using cond as some kind of if:
(cond (<test> <then>) <else>) ;; WRONG
You can have an if as follows:
(if <test> <then> <else>)
For example:
(if (> u v) u v) ;; evaluates to either `u` or `v`, whichever is greater
The cond syntax is a bit more complex but you don't need it yet.
You cannot return-from a block that was undeclared, you probably renamed the function to f3 without renaming that part, or copied that from somewhere else, but in any case return-from is only needed when you have a bigger function and probably a lot more side-effects. Here the computation can be written in a more functionnal way. There is an implicit return in Lisp-like languages, unlike Java, for example below the last (but also single) expression in add evaluates to the function's return value:
(defun add-3 (x)
(+ x 3))
Start with smaller examples and test often, fix any error the compiler or interpreter prints before trying to do more complex things. Also, have a look at the available online resources to learn more about the language: https://common-lisp.net/documentation
Although the other answers are right: you definitely need to learn more CL syntax and you probably would not solve this problem recursively in idiomatic CL (whatever 'idiomatic CL' is), here's how to actually do it, because thinking about how to solve these problems recursively is useful.
First of all let's write a function max/2 which returns the maximum of two numbers. This is pretty easy:
(defun max/2 (a b)
(if (> a b) a b))
Now the trick is this: assume you have some idea of what the maximum of a list of numbers is: call this guess m. Then:
if the list is empty, the maximum is m;
otherwise the list has a first element, so pick a new m which is the maximum of the first element of the list and the current m, and recurse on the rest of the list.
So, we can write this function, which I'll call max/carrying (because it 'carries' the m):
(defun max/carrying (m list)
(if (null list)
m
(max/carrying (max/2 (first list) m)
(rest list))))
And this is now almost all we need. The trick is then to write a little shim around max/carrying which bootstraps it:
to compute the maximum of a list:
if the list is empty it has no maximum, and this is an error;
otherwise the result is max/carrying of the first element of the list and the rest of the list.
I won't write that, but it's pretty easy (to signal an error, the function you want is error).

Understanding list iteration and function calls in Racket

I'm trying to implement a prolog-like program using Racket. I'm very new to the language still. I was able to write the =or, =and, and == that are seen in the =parent function below, but I'm having trouble with query and I feel like it's a basic misunderstanding given my beginner's status with the language.
Here's the parent function:
(define (=parent x y)
(=or (=and (== x "Cronus") (== y "Zeus"))
(=and (== x "Zeus") (== y "Athena"))
(=and (== x "Athena") (== y "Erichthonius"))))
Here's the expected use:
(query (option) (=parent "Zeus" option))
...which will succeed when option is Athena.
I've given it a number of different attempts, but am always getting the wrong output and behavior. I initially tried to use the local-binding of let but I've simplified it even further and it still isn't working:
(define query
(lambda (arg1 arg2)
(for/list ([i (in-list arg1)])
(ormap (λ (x) arg2 x) i))))
I also took the approach of defining option as so:
(define (option)
(list '(Zeus Athena Erichthonius Cronus)))
Running the query code as shown above always results with an output of '(Zeus).
In the debugger, when I set a breakpoint at the for/list line, I see i => (Zeus Athena Erichthonius Cronus) and i never changes before query returns. I thought the code I wrote would iterate through the list, assigning i to each element, but that's not the case here. So where am I going wrong?
In addition, in each step through the debugger, I never enter the (=parent x y) function. And I'm not understanding why it isn't being called.
My last question: why can't I define option using a list of strings? (it produces: ormap: contract violation, expected: list? given: "Zeus"
(define (option)
(list "Zeus" "Athena" "Erichthonius" "Cronus"))

Reversing the function usage in compose function

The compose function applies last function first, i.e. it applies sent functions in reverse order. For example:
((compose sqrt add1) 8)
Above will add1 to 8 and then find sqrt of 9.
I want to create a mycompose function which applies first sent function first, and then second, third etc. Hence, in above example, sqrt needs to be applied first and then add1. I could manage following:
(define (mycompose L arg)
(let loop ((L L)
(res arg))
(cond
[(empty? L) res]
[else (loop (rest L) ((car L) res))])))
(mycompose (list sqrt add1) 8)
I am sure there is a better way. Especially, can above be achieved using macros and also permit multiple arguments to be sent to each function turn by turn?
This “reverse composition” that you describe is often called thrush, and the point-free package provides a thrush function that does precisely what you want. However, let’s say you wanted to implement it yourself. Well, the easiest way would be to reuse the existing implementation of compose, since thrush is just compose with the arguments reversed:
(define (thrush . fs)
(apply compose (reverse fs))
This is, in fact, how the point-free package implements thrush. Still, this might be unsatisfying to you, since you don’t know how compose is implemented. Well, fortunately, we can implement thrush from scratch with a simple fold:
(define (thrush . fs)
(for/fold ([f values])
([g (in-list fs)])
(λ args (call-with-values (thunk (apply f args)) g))))
The real trick here is the use of call-with-values, which properly handles functions that return multiple values. Just like Racket’s compose, this will accept multiple values and pass them along to functions later in the pipeline as multiple arguments, creating a nice symmetry between function inputs and function outputs.

How to express lisp (lambda (pair) (apply #'f pair)) more simply?

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).

Something like find in lisp

is there a function like find in lisp that returns true instead of the element we're trying to find?
example:
I want it to do
(find 'x '(a c x)) = t
not
(find 'x '(a c x)) = x
Also, the reason I am asking is because I am trying to reach the deepest element in a list. My plan was to flatten the list every time i recursively called it.
I would then stop the recursive call when
(mapcar 'atom list)
would tell me every atom in there is true.
Do you believe this is a good approach to this problem?
There's no such function, but it can't be easier to write one:
(defun find-t (&rest args)
(when (apply #'find args)
t))
Also instead of (mapcar 'atom list) you can use (every #`(eql t %) list), i.e. check that every item in list is exactly t. (Here #`() is syntactic sugar for one-argument lambdas, that I use.)
But overall it's unclear, what you're trying to achieve with all this. Can you elaborate on what you're trying to do?