returning multiple values from multiple functions? - common-lisp

Often, I have main functions that run multiple functions in my common lisp apps.
(main
(run-function-1...)
(run-function-2...)
(run-function-3...)
(run-function-4...)
(run-function-5...))
At the moment, I have this situation where each function in main returns a varying number of values. However, the number of return values are also fixed.
I want main to return all values from all function.
(main
(run-function-1...) ;<--- returns 2 values
(run-function-2...) ;<--- returns 2 values
(run-function-3...) ;<--- returns 1 values
(run-function-4...) ;<--- returns 3 values
(run-function-5...)) ;<--- returns 2 values
;; main should return 10 values
When I do multiple-value-bind inside of main it doesnt capture all function returns. Because it only accepts one value-form.

You could use multiple-value-list + append + values-list, but I think the most straightforward is multiple-value-call:
(multiple-value-call #'values
(run-function-1 ...)
(run-function-2 ...)
(run-function-3 ...)
(run-function-4 ...)
(run-function-5 ...))
If you want to return a list, replace #'values with #'list.

You have to repack the returned values into a new values call:
(defun run-function-1 ()
(values 1 2))
(defun run-function-2 ()
(values 3 4 5))
(defun main ()
(multiple-value-bind (a b) (run-function-1)
(multiple-value-bind (c d e) (run-function-2)
(values a b c d e))))
(main)
1 ;
2 ;
3 ;
4 ;
5

Related

smlnj - Function That Adds Even and Odd Elements In An Int List

I am fairly new to functional programming and I do not understand my error here. I am trying to make a function that takes an integer list and returns both the sum of the even elements and the sum of the odd elements. The error I am getting is in line 1, and it states: "Error: right-hand-side of clause doesn't agree with function result type [overload conflict] ...". I don't understand the error, and I would appreciate any help in understanding my error.
fun add(nil) = 0
| add([x]) = x
| add(x :: xs) =
let
val evenList = xs;
val oddList = x :: xs
in
(hd evenList + add(tl(tl(evenList))), hd oddList + add(tl(tl(oddList))))
end;
The reason for the type error is that the function should return a pair, but your base cases don't.
I suspect you got to that code by thinking about skipping every other element, dividing the list by skipping.
There's a different way to approach this.
Consider the list [a,b,c,d].
Counting from 1, the elements are numbered
1 2 3 4
a b c d
Now consider the positions in the tail of the list.
They are
1 2 3
b c d
That is, odd positions in the tail are even positions in the entire list, and even positions in the tail are odd in the entire list.
This means that if we recursively compute "odds and evens" in the tail, we will get the sums from the tail, where its "odds" is our "evens", and if we add our head to the tail's "evens", we will get the "odds" we want.
All we need now is a good base case – and the sums of an empty list must be (0, 0).
Something like this:
fun add [] = (0,0)
| add (x::xs) = case add xs of
(odds, evens) => (x + evens, odds)
or, you can deconstruct the recursive result with a let-binding instead of case:
fun add [] = (0,0)
| add (x::xs) = let val (odds, evens) = add xs
in
(x + evens, odds)
end

Transform List (Generator a) into Generator (List a)

Here is a simplified version of my problem: Generate a list of random values in which each consecutive value depends on the previous one.
For example, generate a list of random Int, in which each consecutive value will establish minimum for the next step. Let's assume that starting value = 0 and maximum value is always currentValue + 5 :
First step: Random.int 0 5 => 3
Next: Random.int 3 8 => 4
Next: Random.int 4 9 => 8
etc.
Here is my approach:
intGen : Int -> List (Rnd.Generator Int) -> List (Rnd.Generator Int)
intGen value list =
if length list == 10 then
list
else
let newValue = Rnd.int value (value + 5)
newList = newValue :: list
in intGen newValue newList
Let's transform it into Rnd.Generator (List Int):
listToGen : List (Rnd.Generator Int) -> Rnd.Generator (List Int)
listToGen list =
foldr
(Rnd.map2 (::))
(Rnd.list 0 (Rnd.int 0 1))
list
I don't like this part: (Rnd.list 0 (Rnd.int 0 1)). It generates initial value of type Rnd.Generator (List Int), in which (Rnd.int 0 1) is actually never used but is needed by type checking. I would like to skip this part somehow or replace it with something more generic. Is it possible or my implementation is erroneous?
Here is one solution which uses andThen and map. The first parameters is the number of elements you want in the list. The second parameter is the starting value.
intGen : Int -> Int -> Rnd.Generator (List Int)
intGen num value =
if num <= 0 then
constant []
else
Rnd.int value (value + 5)
|> Rnd.andThen (\i -> intGen (num-1) i
|> Rnd.map (\rest -> i :: rest))
To match your example of a list of size 10 starting with 0 as the first low value, you would call this as intGen 10 0.
constant is a generator from elm-community/random-extra, or it can be defined simply like this (because it isn't exposed in the core Elm codebase):
constant : a -> Rnd.Generator a
constant a = Rnd.map (\_ -> a) (Rnd.int 0 1)
Regarding your example, I don't think you would want to use List (Rnd.Generator Int) because that implies a list of generators that aren't tied together in any way. That's why we need to use andThen to pull out the random value just generated, call intGen recursively minus one, then use map to put the list together.

How to replace symbols by their value in a R function body

This code reveals that f doesn't yet look up q before it's called.
q <- 2
f <- function(x) q + x
f
I want to tell R which symbols in the body to look up right away (in this case list("q")) and have it modify f accordingly. How can it be done?
In Common Lisp this would look like:
CL-USER> (defparameter q 4)
Q
CL-USER> (let ((bar q))
(defmacro f (x)
`(+ ,bar ,x)))
F
CL-USER> (macroexpand-1 `(f 4))
(+ 4 4)
T
In R this could look like:
> q = 2
> f = eval(bquote(function(x) .(q) + x))
> f
function (x)
2 + x
>
Since R is interpreted, eval is par for the course there. With Common Lisp, if you do not want to use eval, you can go with a compile-time macro that carries along with it a hard-coded value for 'q, so that every time it is used in code at that point on it refers to the value of 'q at creation time of the macro.
Actually you are wrong about what happens when you make an assignment for a token of the value of function. Take a look at this:
> environment(f)$q
[1] 2
Some of the base R function keep values hidden away in the environments of the returned objects. The two that come to mind are ecdf and splinefun.
You could use something like this:
f_generator = function(q){
q
function(x){
q + x
}
}
f2 = f_generator(2)
f3 = f_generator(3)
f2(1)
# 3
f3(1)
# 4

Lisp, why is this number not a float

Using Common Lisp I am trying loop through a list of students and if the GPA is greater than or equal to 3.0 I want to push a 1 onto another list called equal_names. The problem I am having is the interpreter keeps saying the GPA in the comparison list is "not of type (or rational float)". Why am I getting this error?
Yes, this is for homework. Also this is my first time asking on here, so if you need anything else please let me know.
Sample of the list I am getting the GPA from, where the GPA is 2.307...:
(SETQ students (LIST
(LIST (LIST 'Abbott 'Ashley 'J) '8697387888 'NONE 2.3073320999676614)))
The code I have written:
(setq gpa_count ())
(loop for x in students
if(>= 3.0 (cdr (cdr (cdr x))))
do(push '1 gpa_count))
Given a non-empty list cdr returns the tail of that list, i.e. the list that contains all the elements of the list but the first. The important thing to note is that it returns a list, not an element. That is (cdr (cdr (cdr x))) returns the list (2.30733...), not the float 2.30733.
The loop iterates the outer list. To understand the code in the loop you can look at the first element in students, which is:
'((Abbott Ashley J) 8697387888 NONE 2.3073320999676614)
Now we are going to orientate the list. Every time you pass an element add a d.
Every time you pick a value or go to a list in the list you add an a.
To find how to access the number 2.307.... You look at the first element element in the list:
(Abbott Ashley J) d
8697387888 d
NONE d
Now we are at the part that you are interested in, ie. (2.3073320999676614)), thus you add an a. Now order those in reverse and put a c in front and a r in the end.. It becomes cadddr In light of that your loop should be:
(setq students '(("Mary Larson" 333 NONE 1.1)
("Mina Morson" 333 NONE 2.5)
("Magnus Outsider" 333 NONE 4.1)))
(setq gpa_count ())
(loop for x in students
if (>= 3.0 (cadddr x))
do (push '1 gpa_count))
gpa_count ; ==> (1 1)
Another example:
(setq x (1 (2 3) (3 4 (5 6) 7))) ; ==> (1 (2 3) (3 4 (5 6) 7))
To get the 3*. We follow the parts. 1 == d, (2 3) == a, 2 ==d, 3* == a. In reverse: adad and add c and r to the ends ==> cadadr. thus:
(cadadr '(1 (2 3) (3 4 (5 6) 7))) ; ==> 3
To get the 5. we do the same 1 == d, (2 3) == d and then we have the list we want ==a.
Then 3 ==d, 4 ==d, (5 6) ==a. The 5 is the first element == a. In reverse aaddadd. Now CL guarantees 4 letters accessors so we need to split it up in 4s from the right. Thus it becomes:
(caadr (cdaddr '(1 (2 3) (3 4 (5 6) 7)))) ; ==> 5
Now, without describing you can pick any number or list. Eg. to get (5 6) ddadda, in reverse and split up becomes (cadr (cdaddr x))
Hope it helps.
If your data format is consistent then
(fourth x)
will return the GPA.
Going further,
(setf (symbol-function 'gpa)(function fourth))
would provide
(gpa x)
as "an accessor" for the gpa in the data structure.
My CLISP 2.49 gives this error message:
*** - >=: (2.307332) is not a real number
Let's look at that error message: >=: (2.307332) is not a real number.
The error happens at the call to >= and one argument is a list of a number, not a number.
Since you try to extract the number from a list, does that extract work?
We see that you call CDR. CDR of a list returns a list. So there is the error. You need to extract the number from the list.
Btw., CLISP has commands like help, where, backtrace, ... to further investigate the problem. Just type help and return, without anything else, and you see a list of commands.

Ignoring multiple return values in Racket

In Racket, it's possible to return multiple values from a function by doing e.g.
(define (foo)
(values 1 2 3))
Then we can bind them by doing
(define-values (one two three) (foo))
Now one is bound to 1, two to 2, and three to 3.
I have a function that returns multiple values, but I'm interested only in some of them. Is there a way of extracting the "interesting" return values, while "ignoring" (i.e. not binding) the rest, a la _ pattern in Haskell?
You can use match-let-values or match-define-values for this (depending on whether you want lexical or top-level variables):
> (match-let-values (((_ _ a _) (values 1 2 3 4)))
a)
; => 3
> (match-define-values (_ a _ _) (values 1 2 3 4))
> a
; => 2

Resources