Jump to content

Call a function: Difference between revisions

Add Clojure solution
m (Fix Perl6 -> Raku in comments)
(Add Clojure solution)
Line 1,031:
CALL Foo USING Bar</lang>
 
=={{header|Clojure}}==
Note: I ran all these examples in the REPL so there is no printed output; instead I have denoted the value of each expression evaluated using `;=>'.
 
'''Calling a function that requires no arguments'''
<lang clojure>
(defn one []
"Function that takes no arguments and returns 1"
1)
 
(one); => 1
</lang>
'''Calling a function with a fixed number of arguments'''
<lang clojure>
(defn total-cost [item-price num-items]
"Returns the total price to buy the given number of items"
(* item-price num-items))
 
(total-cost 1 5); => 5
</lang>
'''Calling a function with optional arguments'''
The syntax is exactly the same for the calling code; here's an example of the exact same function as above, except now it takes an optional third argument (discount-percentage)
<lang clojure>
(defn total-cost-with-discount [item-price num-items & [discount-percentage]]
"Returns total price to buy the items after discount is applied (if given)"
(let [discount (or discount-percentage 0)] ;; Assign discount to either the discount-percentage (if given) or default 0 if not
(-> item-price
(* num-items) ;; Calculate total cost
(* (- 100 discount)) ;; Apply discount
(/ 100.0))))
 
;; Now we can use the function without the optional arguments, and see the same behaviour as our total-cost function
(total-cost-with-discount 1 5); => 5
 
;; Or we can add the third parameter to calculate the cost with 20% discount
(total-cost-with-discount 1 5 20); => 4
</lang>
'''Calling a function with a variable number of arguments'''
You can use the optional argument syntax seen above to implement variable numbers, but here's another way to do it by writing multiple functions with different arguments all in one.
 
Once again, calling the function is the same, but you need to know what types of arguments are expected for each arity.
<lang clojure>
(defn make-address
([city place-name] (str place-name ", " city))
([city street house-number] (str house-number " " street ", " city))
([city street house-number apartment] (str house-number " " street ", Apt. " apartment ", " city)))
 
;; To call the function you just need to pass whatever arguments you are supplying as you would with a fixed number
 
;; First case- the queen doesn't need a street name
(make-address "London" "Buckingham Palace"); => "Buckingham Palace, London"
 
;; Second case
(make-address "London" "Downing Street" 10); => "10 Downing Street, London"
 
;; Third case
(make-address "London" "Baker Street" 221 "B"); => "221 Baker Street, Apt. B, London"
</lang>
'''Calling a function with named arguments'''
The way to do this in clojure is to pass the arguments as a map and destructure them by name in the function definition. The syntax is the same, but it requires you to pass a single map argument containing all of your arguments and their names.
<lang clojure>
(defn make-mailing-label [{:keys [name address country]}]
"Returns the correct text to mail a letter to the addressee"
(str name "\n" address "\n" (or country "UK"))) ;; If country is nil, assume it is the UK
 
;; We can call it with all three arguments in a map to get mickey's international address
(make-mailing-label {:name "Mickey Mouse"
:address "1 Disney Avenue, Los Angeles"
:country "USA"}); => "Mickey Mouse\n1 Disney Avenue, Los Angeles\nUSA"
 
;; Or we can call it with fewer arguments for domestic mail
(make-mailing-label {:name "Her Majesty"
:address "Buckingham Palace, London"}); => "Her Majesty\nBuckingham Palace, London\nUK"
</lang>
'''Using a function in statement context'''
I'm not really sure what this means - you can use a function to assign a variable, but there aren't really statements
<lang clojure>
(defn multiply-by-10 [number]
(* 10 number))
 
(def fifty (multiply-by-10 5))
 
fifty; => 50
</lang>
 
'''Using a function in first-class context within an expression'''
 
Functions are always first-class, here are some examples of how they can be used in first class context:
 
You can use one function to create another
<lang clojure>
(defn make-discount-function [discount-percent]
"Returns a function that takes a price and applies the given discount"
(fn [price] (-> price
(* (- 100 discount-percent))
(/ 100.0))))
 
;; Now we can create a '20% off' function to calculate prices with your discount card
(def discount-20pc (make-discount-function 20))
 
;; Use the function to calculate some discount prices
(discount-20pc 100); => 80
(discount-20pc 5); => 4
 
;; Your friend has a better discount card, we can use the same function to create their discount card function
(def discount-50pc (make-discount-function 50))
(discount-50pc 100); => 50
(discount-50pc 5); => 2.5
</lang>
 
You can store functions in collections as if they were variables
<lang clojure>
;; Continuing on the same example, let's imagine Anna has a 20% discount card and Bill has 50%. Charlie pays full price
;; We can store their discount functions in a map
 
(def discount-cards {"Anna" discount-20pc
"Bill" discount-50pc
"Charlie" identity}) ;; Identity returns whatever value was passed to the function (in this case it will be price)
 
;; Now we can access them by cardholder name in another function
(defn calculate-discounted-price [price shopper-name]
"Applies the correct discount for the person"
(let [discount-fn (get discount-cards shopper-name)] ;; Get the right discount function
(discount-fn price))) ;; Apply discount function to the price
 
(calculate-discounted-price 100 "Anna"); => 80
(calculate-discounted-price 100 "Bill"); => 50
(calculate-discounted-price 100 "Charlie"); => 100
</lang>
You can pass functions as arguments to other functions
<lang clojure>;; Here we have two functions to format a price depending on the country
 
(defn format-price-uk [price]
(str "£" price))
 
(defn format-price-us [price]
(str "$" price))
 
;; And one function that takes a price formatting function as an argument
 
(defn format-receipt [item-name price price-formatting-function]
"Return the item name and price formatted according to the function"
(str item-name
" "
(price-formatting-function price))) ;; Call the format function to get the right representation of the price
 
(format-receipt "Loo Roll" 5 format-price-uk); => "Loo Roll £5"
 
(format-receipt "Toilet Paper" 5 format-price-us); => "Toilet Paper $5"
</lang>
'''Obtaining the return value of a function'''
<lang clojure>;;You can assign it to a variable:
 
(def receipt-us (format-receipt "Toilet Paper" 5 format-price-us))
 
;; Then the variable holds the value
receipt-us; => "Toilet Paper $5"
 
;; Or you can use it in a call to another function
 
(defn add-store-name [receipt]
"A function to add a footer to the receipt"
(str receipt "\n Thanks for shopping at Safeway" ))
 
;; Calls add-store-name with the result of the format function
(add-store-name (format-receipt "Toilet Paper" 5 format-price-us)); => "Toilet Paper $5\n Thanks for shopping at Safeway"
</lang>
'''Distinguishing built-in functions and user-defined functions'''
<lang clojure>;; They are indistinguishable in Clojure, and you can even override a built in one
 
;; Using built-in addition
 
(+ 5 5); => 10
 
;; Using custom defined addition
 
(defn ? [a b]
"Returns the sum of two numbers"
(+ a b))
 
(? 5 5); => 10
 
;; Overriding a built in function is possible but not recommended
 
(defn * [a b] ;; Redefining the multiplication operator
"Returns the sum of two numbers"
(+ a b))
 
(* 5 5); => 10
</lang>
'''Distinguishing subroutines and functions'''
<lang clojure>;; They are the same thing - indeed, everything in clojure is a function
;; Functions without return values simply return nil
 
(defn no-return-value [a]
(print (str "Your argument was" a "; now returning nil")))
 
(no-return-value "hi"); => nil
</lang>
'''Stating whether arguments are passed by value or by reference'''
All data structures are immutable, so they are passed by value only.
The value returned from the function does not change the original input
<lang clojure>;; Set up a variable that we will pass to a function
(def the-queen {:name "Elizabeth"
:title "Your Majesty"
:address "Buckingham Palace"
:pets ["Corgi" "Horse"]})
 
;; A function to modify the data
(defn adopt-pet [person pet]
"Adds pet to the person's list of pets"
(update person
:pets
#(conj % pet)))
 
;; Calling the function returns a new data structure with the modified pets
(adopt-pet the-queen "Ferret"); => {:name "Elizabeth":title "Your Majesty" :address "Buckingham Palace" :pets ["Corgi" "Horse" "Ferret]}
 
;; The original data structure is not changed
the-queen; => {:name "Elizabeth" :title "Your Majesty" :address "Buckingham Palace" :pets ["Corgi" "Horse"]}</lang>
 
'''Is partial application possible and how'''
 
Yes, it is similar to the discount card case we saw earlier. Instead of having a function return another function, we can use partial:
 
<lang clojure>(defn apply-discount [discount-percentage price]
"Function to apply a discount to a price"
(-> price
(* (- 100 discount-percentage)) ;; Apply discount
(/ 100.0)))
 
;; Here we have assigned the variable to a partial function
;; It means 'call apply-discount with 10 as the first argument'
(def discount-10pc-option-1 (partial apply-discount 10))
 
;; And is equivalent to this:
(defn discount-10pc-option-2 [price]
(apply-discount 10 price))
 
(discount-10pc-option-1 100); => 90
 
(discount-10pc-option-2 100); => 90
</lang>
=={{header|CoffeeScript}}==
<lang coffeescript>
Cookies help us deliver our services. By using our services, you agree to our use of cookies.