Creating a collection of functions - collections

I have the following function that receives a list of functions:
(defn foo
[fn-list]
(map #(%) fn-list))
I want to pass it instances of this bar function as a parameter.
(defn bar
[x]
(println x))
My problem is that I only have a list of arguments for bar. Fox example, a simple list ("a" "b" "c"). I want to create a list of bar functions, each having as argument, an element of the later collection.
Can someone show me how this can be done? Thanks.
Note: I can't simply replace foo with (map bar ("a" "b" "c")) for reasonable reasons.

I'm not entirely clear what you are trying to do, but perhaps you want something like:
(map #(partial bar %) [1 2 3])
This will create a sequence of functions, which when called (with 0 arguments) will do the equivalent of (bar 1), (bar 2) etc.

Related

SMLNJ powerset function

I am trying to print the size of a list created from below power set function
fun add x ys = x :: ys;
fun powerset ([]) = [[]]
| powerset (x::xr) = powerset xr # map (add x) (powerset xr) ;
val it = [[],[3],[2],[2,3],[1],[1,3],[1,2],[1,2,3]] : int list list;
I have the list size function
fun size xs = (foldr op+ 0 o map (fn x => 1)) xs;
I couldnt able to merge these two functions and get the result like
I need something like this:
[(0,[]),(1,[3]),(1,[2]),(2,[2,3]),(1,[1]),(2,[1,3]),(2,[1,2]),(3,[1,2,3])]
Could anyone please help me with this?
You can get the length of a list using the built-in List.length.
You seem to forget to mention that you have the constraint that you can only use higher-order functions. (I am guessing you have this constraint because others these days are asking how to write powerset functions with this constraint, and using foldr to count, like you do, seems a little constructed.)
Your example indicates that you are trying to count each list in a list of lists, and not just the length of one list. For that you'd want to map the counting function across your list of lists. But that'd just give you a list of lengths, and your desired output seems to be a list of tuples containing both the length and the actual list.
Here are some hints:
You might as well use foldl rather than foldr since addition is associative.
You don't need to first map (fn x => 1) - this adds an unnecessary iteration of the list. You're probably doing this because folding seems complicated and you only just managed to write foldr op+ 0. This is symptomatic of not having understood the first argument of fold.
Try, instead of op+, to write the fold expression using an anonymous function:
fun size L = foldl (fn (x, acc) => ...) 0 L
Compare this to op+ which, if written like an anonymous function, would look like:
fn (x, y) => x + y
Folding with op+ carries some very implicit uses of the + operator: You want to discard one operand (since not its value but its presence counts) and use the other one as an accumulating variable (which is better understood by calling it acc rather than y).
If you're unsure what I mean about accumulating variable, consider this recursive version of size:
fun size L =
let fun sizeHelper ([], acc) = acc
| sizeHelper (x::xs, acc) = sizeHelper (xs, 1+acc)
in sizeHelper (L, 0) end
Its helper function has an extra argument for carrying a result through recursive calls. This makes the function tail-recursive, and folding is one generalisation of this technique; the second argument to fold's helper function (given as an argument) is the accumulating variable. (The first argument to fold's helper function is a single argument rather than a list, unlike the explicitly recursive version of size above.)
Given your size function (aka List.length), you're only a third of the way, since
size [[],[3],[2],[2,3],[1],[1,3],[1,2],[1,2,3]]
gives you 8 and not [(0,[]),(1,[3]),(1,[2]),(2,[2,3]),...)]
So you need to write another function that (a) applies size to each element, which would give you [0,1,1,2,...], and (b) somehow combine that with the input list [[],[3],[2],[2,3],...]. You could do that either in two steps using zip/map, or in one step using only foldr.
Try and write a foldr expression that does nothing to an input list L:
foldr (fn (x, acc) => ...) [] L
(Like with op+, doing op:: instead of writing an anonymous function would be cheating.)
Then think of each x as a list.

Checking if numbers are even or odd in lisp

I need to write a recursive method in lisp that doubles the odd values and leaves the even values alone.
So far i have:
(defun MY-DOUBLE-ODD (n)
(if (oddp n)
(setq n (* n 2)))
n)
However, I just can't figure out how to have this recursive method go through an entire list.
How do I fix it to make it iterate through (MY-DOUBLE-ODD (1 2 3 4 5 6))
??
Your solution should not involve setq at all. The recursion should be used to iterate the list of arguments, using car to get the first element, cdr to get the rest of the list to recurse on, and cons to construct the result on return from the recursive call.

Mapping curry to a list of parameters

I'm doing some exercises in Racket, and ran into a problem I couldn't seem to query the docs for.
I want to generate the following curries of modulo for a list of divisors:
(define multlist '[3 5])
(define modfuncs (map (lambda x ;# make some modulos
(curry modulo x)) multlist))
This produces a list of curried procedures, which sounds promising, but when I try to test one of them, I get the following error:
-> (car modfuncs)
#<procedure:curried>
-> ((car modfuncs) 3)
; modulo: contract violation
; expected: integer?
; given: '(3)
; argument position: 1st
; [,bt for context]
Assuming this isn't a terrible way to do this, how do I unquote the values of multlist passed to the curry/map call so these functions will evaluate correctly?
You're actually doing this correctly, albeit with a tiny mistake:
(lambda x (curry modulo x))
This doesn't do what you think it does. What you actually want is this:
(lambda (x) (curry modulo x))
See the difference? In the former, x is not within an arguments list, so it will actually be passed a list of all arguments passed to the function, not a single argument.
You can see this behavior for yourself with the following simple program:
((lambda x x) 1 2 3)
; => '(1 2 3)
Therefore, your curry function is receiving a list of one number for x, not an actual integer.
So perhaps the more satisfying answer is: why does Racket do this? Well, this is actually a result of Racket/Scheme's rest parameter syntax. Inserting a dot before the last argument of a lambda makes that parameter a rest parameter, which becomes a list that holds all additional parameters passed to the function.
((lambda (a b . rest) rest) 1 2 3 4 5)
; => '(3 4 5)
However, this isn't actually just a special syntax. The dot notation actually has to do with how Racket's reader reads lists and pairs in syntax. The above parameter list actually becomes an "improper" list made up of the following cons sequence:
(cons 'a (cons 'b 'rest))
The same function without the rest parameter would have a proper list as its argument declaration, which would look like this instead:
(cons 'a (cons 'b null))
So then, what about the original x just standing alone? Well, that's an improper list with no preceding arguments! Doing ( . rest) wouldn't make any sense—it would be a syntax error—because you'd be trying to create a pair with no car element. The equivalent is just dropping the pair syntax entirely.

common lisp how can I make my variable act as the operator it holds when it is first in list?

So I am very new to lisp, and not that advanced of a programmer yet. Just getting started really.
I'm messing around trying to get a very simple genetic algorithm going from scratch, and while most of my code seems to execute as desired, I'm stuck with such a simple bug/misunderstanding that I am blocked from the bottom... There is clearly something I am not getting despite my hours online trying to find a solution..
Basically, I know it has something to do with the fact I am trying to call a variable as if it were an operator (which the variable holds) and thus it tells me my function (which is really just a variable holding an operator) is not defined.
The start of my code works fine.
(defvar *nb* 8)
(defvar *random-operators* '(+ - * /))
(defun get-operator ()
"Returns an element of the list of operators chosen at random."
(nth (random (length *random-operators*)) *random-operators*))
So (get-operator) does get me one of the four random operators, as desired.
I used this even simpler code to test the structure of my code, and it works as desired.
(defun ga-simple ()
"Returns the value of genome once it matches *nb* and prints
the number of generations required."
(do ((genome (random 10) (random 10))
(generation-counter 1 (incf generation-counter)))
((eql genome *nb*)
(format t
"The solution is ~S, and it took ~D generations"
genome
generation-counter))))
The problem comes when I try and create a genome composed of three variables, one holding the operator, and the other two, the integers.
(defun ga-with-operator ()
(do ((genome 42 (opr1 int1 int2))
(generation-counter 0 (incf generation-counter))
(opr1 + (get-operator)
(int1 (random 10) (random 10))
(int2 (random 10) (random 10))
((eql genome *nb*)
(format t
"The solution is ~S, and it took ~D generations"
genome
generation-counter))))
my compiler warnings tell me where the problem is...
;Compiler warnings for "./ga-one.lisp" :
; In GA-WITH-OPERATOR: Unused lexical variable OPR1
;Compiler warnings for "./ga-one.lisp" :
; In GA-WITH-OPERATOR: Undefined function OPR1/
And so clearly a call to the function (ga-with-operator) says opr1 is an undefined-function-call. So from what I gather when the "do" macro checks the increment condition for the variable genome, it reads the list, expecting opr1 to be an operator and not a variable holding an operator... Now, an operator simply entered works perfect here, but I don't know how to make lisp use the evaluated value of opr1, which is an operator, as the operator for the integers...
To simplify, I made a function trying to construct a single genome using my get-operator function, and failed hard even there lol
(defun get-genome ()
(let ((operator1 (get-operator)))
(operator1 (random 10) (random 10))))
So I made a test-let function to make sure my "let" variable assignment is right...
(defun test-let ()
(let ((rand (get-operator)))
(print rand)))
Which it does... So now I am getting desperate and missing something obviously very simple and yet crucial to make it all stick together.
If someone could explain to me, or just show me, how to get the simple (get-genome) function to work I would really appreciate it. I know lisp expects an operator as the first element in the list, and my error stems from me feeding it a variable holding an operator instead... How do I convince it my variable is the operator it is holding?
in case anyone wants to know the working code...
(defvar *nb* 42)
(defvar *random-operators* '(+ - * /))
(defun get-operator ()
"Return an element of the list of operators chosen at random."
(nth (random (length *random-operators*)) *random-operators*))
(defun get-genome ()
(let ((operator1 (get-operator)))
(funcall operator1 (+ 1 (random 9)) (+ 1 (random 9)))))
(defun ga-with-operator ()
(do ((genome (get-genome) (get-genome))
(generation-counter 0 (1+ generation-counter)))
((eql genome *nb*)
(format t "The solution is ~S, and it took ~D generations"
genome generation-counter))))
In Common Lisp you need to use FUNCALL if the function is returned by a function or if the function is stored in a variable.
(defun get-genome ()
(let ((operator1 (get-operator)))
(funcall operator1 (random 10) (random 10))))
Common Lisp has different namespaces for functions and for values. Thus a name can both be a variable and a function:
(defun foo (list)
(list list list))
The first list in the last line calls the global function called list and the second and third are actually the local variable list.
(defun ga-with-operator ()
(do ((genome 42 (opr1 int1 int2))
(generation-counter 0 (incf generation-counter))
(opr1 + (get-operator)
(int1 (random 10) (random 10))
(int2 (random 10) (random 10))
((eql genome *nb*)
(format t
"The solution is ~S, and it took ~D generations"
genome
generation-counter))))
Above function has more problems.
Can you see the first? Hint: try indenting it correctly. Are the parentheses correct?
also: + is not a function. It is a variable in your code. To make it a function you would need to quote or function quote it. '+ or #'+.
you also don't need to INCF the generation-counter. Just adding 1 is fine. The DO loop updates the variable. Use (1+ generation-counter).
Of course, FUNCALL / APPLY is what you want, but just to complete the picture, note that this also works:
(setf (symbol-function 'operator1) (get-operator))
(operator1 (+ 1 (random 9)) (+ 1 (random 9)))
The reason you generally don't want to do this is that binding of the symbol-function slot is global.

Add an element to a global variable

I'm new to lisp and I have a problem when adding an element to an existing list.
> (setq l '(1 2))
(1 2)
> (append l 3)
(1 2 . 3)
> l
(1 2)
> (append l '(3))
(1 2 3)
> l
(1 2)
> (list l '(3))
((1 2) (3))
> l
(1 2)
> (cons 3 l)
(3 1 2)
> l
(1 2)
> (push 3 l)
(3 1 2)
> l
(3 1 2)
The example above is what I made on commandline. Here only push works. But even push doesn't add the element when I execute the code that I write in a file (and load it on commandline). My code example is available in another question's page.
How can I update the original l so that it adds 3 to itself? I tried several other functions (cons, list) but the result was the same/similar - 3 wasn't added to the original list.
So you are pushing a value onto a list which is passed as a function parameter? That doesn't work; push creates a new cons cell, makes it point to the original list, and sets the variable to refer to the new cons cell. Unfortunately, setting a function parameter inside the function doesn't do anything to the variable which was passed originally (from outside the function).
When you call a function, the arguments are first evaluated. So if you pass l to a function, what is actually passed is the value of l. Nothing which happens inside the function can change what l refers to (outside the function).
If you want to make something like a function, but which actually changes the values of the variables used as parameters, you need to write a macro. Or, just make the function return the needed value, and set the original variable outside the function, after you get the return value back. Something like this:
(setf l (my-function l))
OR, you could use an extra level of indirection: make l refer to a "dummy" cons cell, which points to the "real" list, and change the cdr of the "dummy" cons from inside your function. This is poor style, however; it's usually better to use return values, rather than "returning" data in modified arguments.
Note that if you need to return more than one value, that doesn't mean you need to modify arguments; Common Lisp can return more than one value from a function, using (values).

Resources