How to make a Clojure function take a variable number of parameters? - function

I'm learning Clojure and I'm trying to define a function that take a variable number of parameters (a variadic function) and sum them up (yep, just like the + procedure). However, I don´t know how to implement such function
Everything I can do is:
(defn sum [n1, n2] (+ n1 n2))
Of course this function takes two parameteres and two parameters only. Please teach me how to make it accept (and process) an undefined number of parameters.

In general, non-commutative case you can use apply:
(defn sum [& args] (apply + args))
Since addition is commutative, something like this should work too:
(defn sum [& args] (reduce + args))
& causes args to be bound to the remainder of the argument list (in this case the whole list, as there's nothing to the left of &).
Obviously defining sum like that doesn't make sense, since instead of:
(sum a b c d e ...)
you can just write:
(+ a b c d e ....)

Yehoanathan mentions arity overloading but does not provide a direct example. Here's what he's talking about:
(defn special-sum
([] (+ 10 10))
([x] (+ 10 x))
([x y] (+ x y)))
(special-sum) => 20
(special-sum 50) => 60
(special-sum 50 25) => 75

(defn my-sum
([] 0) ; no parameter
([x] x) ; one parameter
([x y] (+ x y)) ; two parameters
([x y & more] ; more than two parameters
(reduce + (my-sum x y) more))
)

defn is a macro that makes defining functions a little simpler.
Clojure supports arity overloading in a single function object,
self-reference, and variable-arity functions using &
From http://clojure.org/functional_programming

(defn sum [& args]
(print "sum of" args ":" (apply + args)))
This takes any number of arguments and add them up.

Related

Where is the argument coming from?

You can notice the v in the lambda in the function body, where is the v coming from, what it is based on?
(define (cached-assoc xs n)
(letrec ([memo (make-vector n #f)]
[acc 0]
[f (lambda(x)
(let ([ans (vector-assoc x memo)])
(if ans
(cdr ans)
(let ([new-ans (assoc x xs)])
(begin
(vector-set! memo acc (cons x new-ans))
(set! acc (if (= (+ acc 1)) 0 (+ acc 1)))
new-ans)))))])
(lambda (v) (f v))))
The whole expression is returning a lambda as a result, and in that lambda there's a formal parameter named v. It doesn't have a value yet, you'll need to call the lambda to bind a value to v and produce a result (assuming the code is working):
((letrec ([memo (make-vector n #f)] ; notice the extra opening `(`, we want to call the returned lambda
[acc 0]
[f (lambda(x)
(let ([ans (vector-assoc x memo)])
(if ans
(cdr ans)
(let ([new-ans (assoc x xs)])
(begin
(vector-set! memo acc (cons x new-ans))
(set! acc (if (= (+ acc 1)) 0 (+ acc 1)))
new-ans)))))])
(lambda (v) (f v)))
10) ; <- the value 10 gets bound to `v`
However, your code isn't right. You are referring to variables named n and xs, but they are not defined anywhere and need a value of their own. The procedure vector-assoc doesn't exist. Also, the lambda at the end is redundant, you could simply return f, there's no need to wrap it in an additional lambda. Finally: you should define the whole expression with a name, it'll make it easier to call it.
I won't go into more details because first you need to fix the function and make it work, and is not clear at all what you want to do - but that should be a separate question.

Is this possible to define a function with no arguments in racket?

I'm trying to define a function in Racket which takes no arguments. All the examples that I have seen take one or more arguments.
How can I do that?
(define (fun1)
"hello")
(define fun2
(lambda ()
"world"))
(define fun3
(thunk
"I am back"))
(fun1)
=> "hello"
(fun2)
=> "world"
(fun3)
=> "I am back"
EDIT
If, as #Joshua suggests, you want a procedure which can take any argument(s) and ignore them, the equivalent definitions would be:
(define (fun1 . x)
"hello")
(define fun2
(lambda x
"world"))
(define fun3
(thunk*
"I am back"))
(fun1)
(fun1 1 2 3)
=> "hello"
(fun 2)
(fun2 4 5 6 7)
=> "world"
(fun3)
(fun3 8 9)
=> "I am back"
The answer can be found in HtDP 2e here:
http://www.ccs.neu.edu/home/matthias/HtDP2e/part_one.html#%28part._sec~3afuncs%29
"...Here are some silly examples:
(define (f x) 1)
(define (g x y) (+ 1 1))
(define (h x y z) (+ (* 2 2) 3))"
...then later...
"The examples are silly because the expressions inside the functions do not involve the variables. Since variables are about inputs, not mentioning them in the expressions means that the function’s output is independent of their input. We don’t need to write functions or programs if the output is always the same." (emphasis mine)
That is the answer to your question: you do not need to define no-argument functions, just define them as constants.
So instead of:
(define (fun) "hello")
You just need:
(define not-a-fun "hello")
You can simply say
(define (hello-world)
(displayln "Hello world"))
(hello-world)

Defining a Racket Function?

I'm supposed to define the function n! (N-Factorial). The thing is I don't know how to.
Here is what I have so far, can someone please help with this? I don't understand the conditionals in Racket, so an explanation would be great!
(define fact (lambda (n) (if (> n 0)) (* n < n)))
You'll have to take a good look at the documentation first, this is a very simple example but you have to understand the basics before attempting a solution, and make sure you know how to write a recursive procedure. Some comments:
(define fact
(lambda (n)
(if (> n 0)
; a conditional must have two parts:
; where is the consequent? here goes the advance of the recursion
; where is the alternative? here goes the base case of the recursion
)
(* n < n))) ; this line is outside the conditional, and it's just wrong
Notice that the last expression is incorrect, I don't know what it's supposed to do, but as it is it'll raise an error. Delete it, and concentrate on writing the body of the conditional.
The trick with scheme (or lisp) is to understand each little bit between each set of brackets as you build them up into more complex forms.
So lets start with the conditionals. if takes 3 arguments. It evaluates the first, and if that's true, if returns the second, and if the first argument is false it returns the third.
(if #t "some value" "some other value") ; => "some value"
(if #f "some value" "some other value") ; => "some other value"
(if (<= 1 0) "done" "go again") ; => "go again"
cond would work too - you can read the racket introduction to conditionals here: http://docs.racket-lang.org/guide/syntax-overview.html#%28part._.Conditionals_with_if__and__or__and_cond%29
You can define functions in two different ways. You're using the anonymous function approach, which is fine, but you don't need a lambda in this case, so the simpler syntax is:
(define (function-name arguments) result)
For example:
(define (previous-number n)
(- n 1))
(previous-number 3) ; => 2
Using a lambda like you have achieves the same thing, using different syntax (don't worry about any other differences for now):
(define previous-number* (lambda (n) (- n 1)))
(previous-number* 3) ; => 2
By the way - that '*' is just another character in that name, nothing special (see http://docs.racket-lang.org/guide/syntax-overview.html#%28part._.Identifiers%29). A '!' at the end of a function name often means that that function has side effects, but n! is a fine name for your function in this case.
So lets go back to your original question and put the function definition and conditional together. We'll use the "recurrence relation" from the wiki definition because it makes for a nice recursive function: If n is less than 1, then the factorial is 1. Otherwise, the factorial is n times the factorial of one less than n. In code, that looks like:
(define (n! n)
(if (<= n 1) ; If n is less than 1,
1 ; then the factorial is 1
(* n (n! (- n 1))))) ; Otherwise, the factorial is n times the factorial of one less than n.
That last clause is a little denser than I'd like, so lets just work though it down for n = 2:
(define n 2)
(* n (n! (- n 1)))
; =>
(* 2 (n! (- 2 1)))
(* 2 (n! 1))
(* 2 1)
2
Also, if you're using Racket, it's really easy to confirm that it's working as we expect:
(check-expect (n! 0) 1)
(check-expect (n! 1) 1)
(check-expect (n! 20) 2432902008176640000)

Clojure function in let binding

If I have a function that evaluates to a function
(defn func1 [c1 c2]
(fn [x1 x2]
...do some stuff with c1 c2 x1))
that I use elsewhere in a map or reduce, is it better to use inline
(defn func2 [x y z]
(reduce (func1 x y) z (range 20)))
or to let bind it first
(defn func2 [x y z]
(let [ffunc (func1 x y)]
(reduce ffunc z (range 20))))
In the first case I would be worried that a new function over x and y is generated each step through the reduce.
The evaluation of the function call (func1 x y) is done once in each case.
The rule for evaluating a function call in Clojure consists of evaluating all the expressions that are provided as its arguments and then invoking the function with those values.
If you define the following higher order function:
(defn plus []
(println "calling plus")
+)
And then call reduce in the following way:
(reduce (plus) [0 1 2 3])
A single calling plus is printed, showing the function plus is invoked only once.
The same thing happens when using the let form:
(let [f (plus)]
(reduce f [0 1 2 3]))
Hope it helps.

How to build a vector via a call to reduce

I'm trying to figure why this particular function isn't working as expected. I suspect from the error message that it has something to do with the way I'm creating the empty vector for the accumulator.
I have a simple function that returns a sequence of 2-element vectors:
(defn zip-with-index
"Returns a sequence in which each element is of the
form [i c] where i is the index of the element and c
is the element at that index."
[coll]
(map-indexed (fn [i c] [i c]) coll))
That works fine. The problem comes when I try to use it in another function
(defn indexes-satisfying
"Returns a vector containing all indexes of coll that satisfy
the predicate p."
[p coll]
(defn accum-if-satisfies [acc zipped]
(let [idx (first zipped)
elem (second zipped)]
(if (p elem)
(conj acc idx)
(acc))))
(reduce accum-if-satisfies (vector) (zip-with-index coll)))
It compiles, but when I attempt to use it I get an error:
user=> (indexes-satisfying (partial > 3) [1 3 5 7])
ArityException Wrong number of args (0) passed to: PersistentVector
clojure.lang.AFn.throwArity (AFn.java:437)
I can't figure out what's going wrong here. Also if there is a more 'Clojure-like' way of doing what I'm trying to do, I'm interested in hearing about that also.
The problem is probably on the else clause of accum-if-satisfies, should be just acc not (acc).
You could use filter and then map instead of reduce. Like that:
(map #(first %)
(filter #(p (second %))
(zip-with-index coll)))
You could also call map-indexed with vector instead of (fn [i c] [i c]).
The whole code would look like that:
(defn indexes-satisfying
[p coll]
(map #(first %)
(filter #(p (second %))
(map-indexed vector coll))))
As for a more Clojure-like way, you could use
(defn indexes-satisfying [pred coll]
(filterv #(pred (nth coll %))
(range (count coll))))
Use filter instead of filterv to return a lazy seq rather than a vector.
Also, you should not use defn to define inner functions; it will instead define a global function in the namespace where the inner function is defined and have subtle side effects besides that. Use letfn instead:
(defn outer [& args]
(letfn [(inner [& inner-args] ...)]
(inner ...)))
One more way to do it would be:
(defn indexes-satisfying [p coll]
(keep-indexed #(if (p %2) % nil) coll))