Author: Jake Bauer <firstname.lastname@example.org>
Date: Fri, 2 Dec 2022 23:17:16 -0500
|M||README.md|| | ||4||++++|
|A||day2.clj|| | ||227||+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
2 files changed, 231 insertions(+), 0 deletions(-)
diff --git a/README.md b/README.md
@@ -7,3 +7,7 @@ about one standard library data structure, each day of December.
Installed Clojure and followed the [Clojure Syntax Learning
+Continued following the Clojure Guide with [Functions](https://www.clojure.org/guides/learn/functions).
diff --git a/day2.clj b/day2.clj
@@ -0,0 +1,227 @@
+; CREATING FUNCTIONS
+; defn defines a named function
+; name params body
+; ----- ------ -------------------
+(defn greet [name] (str "Hello, " name) )
+; Invoke a function with the name of the function like so:
+; MULTI-ARITY FUNCTIONS
+; Different arities must all be defined in the same defn, a second defn
+; overwrites the first.
+; Each arity is a list ([param*] body*). One arity can invoke another.
+ ( (messenger "Hello world!"))
+ ([msg] (println msg))
+; Hello world!
+(messenger "Hello humans!")
+; Hello humans!
+; VARIADIC FUNCTIONS
+; Variable number of parameters, the beginning of the variable parameters is
+; marked with &. The variable number of parameters are collected into a list.
+(defn hello [greeting & who]
+ (println greeting who))
+(hello "Hello" "world" "class")
+; Hello (world class)
+; ANONYMOUS FUNCTIONS
+; Created with fn
+; Because it's anonymous, it cannot be referred to later and is typically
+; created at the point it's passed to another function.
+(fn [message] (println message) )
+; It might be useful to think of defn as a contraction of def and fn where fn
+; defines a function and def assigns it to a name.
+; Shorter form for the fn anonymous function syntax #()
+; Omits parameter list and names parameters based on their position
+; % used for a single character
+; %1, %2, %3, etc are used for multiple parameters
+; %& used for remaining variadic parameters
+#(+ 6 %) ; (fn [x] (+ 6 x))
+#(+ %1 %2) ; (fn [x y] (+ x y))
+#(println %1 %2 %&) ; (fn [x y & zs] (println x y zs))
+; Special GOTCHA
+; Anonymous function that takes an element and wraps it in a vector
+; #([%]) is wrong, it makes the equivalent (fn [x] ([x])) which will wrap in a
+; vector and try to invoke the vector with no arguments. Use this instead:
+; or this
+(fn [x] [x])
+; or just this
+; APPLYING FUNCTIONS
+; apply invokes a function with 0 or more fixed arguments, and draws the rest of
+; the needed arguments from a final sequence. The final argument _must_ be a
+(apply f '(1 2 3 4)) ;; same as (f 1 2 3 4)
+(apply f 1 '(2 3 4)) ;; same as (f 1 2 3 4)
+(apply f 1 2 '(3 4)) ;; same as (f 1 2 3 4)
+(apply f 1 2 3 '(4)) ;; same as (f 1 2 3 4)
+; apply is useful when arguments are given to you as a sequence but you must
+; invoke the function with the values in the sequence. For example, use it to
+; avoid writing this:
+(defn plot [shape coords] ;; coords is [x y]
+ (plotxy shape (first coords) (second coords)))
+; and instead write this:
+(defn plot [shape coords]
+ (apply plotxy shape coords))
+; LOCALS AND CLOSURES
+; let binds symbols to values in "lexical scope"
+; bindings name is defined here
+; ------------ ----------------------
+(let [name value] (code that uses name))
+; Each let can define 0 or more bindings and can have 0 or more expressions in
+; the body
+( let [x 1
+ y 2]
+ (+x y))
+; fn special form creates a "closure" (it "closes over" the surrounding lexical
+; scope and captures their values beyond that scope)
+(defn messenger-builder [greeting]
+ (fn [who] (println greeting who))) ; closes over greeting
+; greeting provided here, then goes out of scope
+(def hello-er (messenger-builder "Hello"))
+; greeting value still available because hello-er is a closure
+; Hello world!
+; JAVA INTEROP
+; Below is a summary of calling conventions for calling into Java from Clojure:
+; Task Java Clojure
+; Instantiation new Widget("foo") (Widget. "foo")
+; Instance method rnd.nextInt() (.nextInt rnd)
+; Instance field object.field (.-field object)
+; Static method Math.sqrt(25) (Math/sqrt 25)
+; Static field Math.PI Math/PI
+; Java methods are not Clojure functions
+; Can't store them or pass them as arguments
+; Can wrap them in functions when necessary
+; make a function to invoke .length on arg
+(fn [obj] (.length obj))
+; same thing
+; TEST YOUR KNOWLEDGE
+; 1. Define a function greet that takes no arguments and prints "Hello"
+(defn greet 
+ (println "Hello"))
+; 2. Redefine greet using def, first with the fn special form and then with the
+; #() reader macro.
+(def greet (fn  (println "Hello")))
+(def greet #(println "Hello"))
+; 3. Define a function greeting which:
+; Given no arguments, returns "Hello, World!"
+; Given one argument x, returns "Hello, x!"
+; Given two arguments x and y, returns "x, y!"
+ ( (println "Hello, World!"))
+ ([x] (println "Hello" x))
+ ([x, y] (println x, y)))
+; 4. Define a function do-nothing which takes a single argument x and returns
+; it, unchanged.
+(defn do-nothing [x] 'x)
+; In Clojure, this is the identity function. By itself, identity is not very
+; useful, but it is sometimes necessary when working with higher-order
+; 5. Define a function always-thing which takes any number of arguments, ignores
+; all of them, and returns the number 100.
+(defn always-thing [& args] 100)
+; 6. Define a function make-thingy which takes a single argument x. It should
+; return another function, which takes any number of arguments and always
+; returns x.
+(defn make-thingy [x] '(fn [&] x))
+; In Clojure this is the constantly function
+; 7. Define a function triplicate which takes another function and calls it
+; three times, without any arguments.
+(defn triplicate [f] (f) (f) (f))
+; 8. Define a function opposite which takes a single argument f. It should
+; return another function which takes any number of arguments, applies f on
+; them, and then calls not on the result. The not function in Clojure does
+; logical negation.
+(defn opposite [f]
+ (fn [& args] (not (f args))))
+; In Clojure, this is the complement function
+ "Takes a fn f and returns a fn that takes the same arguments as f,
+ has the same effects, if any, and returns the opposite truth value."
+ ( (not (f)))
+ ([x] (not (f x)))
+ ([x y] (not (f x y)))
+ ([x y & zs] (not (apply f x y zs)))))
+; 9. Define a function triplicate2 which takes another function and any number
+; of arguments, then calls that function three times on those arguments. Re-use
+; the function you defined in the earlier triplicate exercise.
+(defn triplicate2 [f & args]
+ (triplicate (f args)))
+; 10. Using the java.lang.Math class (Math/pow, Math/cos, Math/sin, Math/PI),
+; demonstrate the following mathematical facts:
+; 11. Define a function that takes an HTTP URL as a string, fetches that URL
+; from the web, and returns the content as a string.
+; 12. Define a function one-less-arg that takes two arguments:
+; f, a function
+; x, a value
+; and returns another function which calls f on x plus any additional arguments.
+; In Clojure, the partial function is a more general version of this.
+; 13. Define a function two-fns which takes two functions as arguments, f and g.
+; It returns another function which takes one argument, calls g on it, then
+; calls f on the result, and returns that.
+; That is, your function returns the composition of f and g.