This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # bangalore-clj (1)
- # beginners (187)
- # braveandtrue (52)
- # calva (7)
- # cider (17)
- # cljs-dev (14)
- # clojure (27)
- # clojure-austin (4)
- # clojure-dev (11)
- # clojure-finland (4)
- # clojure-italy (5)
- # clojure-nl (1)
- # clojure-russia (22)
- # clojure-spec (9)
- # clojure-uk (27)
- # clojurescript (91)
- # datomic (40)
- # duct (4)
- # emacs (14)
- # figwheel-main (36)
- # fulcro (11)
- # hoplon (10)
- # immutant (9)
- # instaparse (4)
- # java (1)
- # jobs (2)
- # off-topic (28)
- # pedestal (1)
- # reagent (15)
- # reitit (7)
- # remote-jobs (6)
- # ring-swagger (3)
- # shadow-cljs (28)
- # slack-help (1)
- # spacemacs (4)
- # specter (1)
- # sql (3)
- # testing (3)
- # tools-deps (24)
in the functional-programming chapter with pegthing
(defn tri* ...) and later on
(def tri (tri*)) many functions refer to
tri (without the star). What is the idea behind this?
e.g. this function refers to
tri and not
(defn triangular? "Is the number triangular? e.g. 1, 3, 6, 10, 15, etc" [n] (= n (last (take-while #(>= n %) tri))))
In this particular example,
tri* is a function that calculates a lazy sequence. Without the star it's just a
def, not a
defn, so it's basically using the
tri* function to calculate the sequence for you one time so that you can then use it more than once without re-calculating it.
In other words it's like a singleton: once you've run
tri* once, you don't need to run it again. Just keep a copy in
tri and use that sequence.
The page reads
The next expression calls tri*, actually creating the lazy sequence and binding it to tri:
(def tri (tri*))
/end quote. What does actually creating mean here? Because it seems like we’re just binding the function to another name.
Is it like this?
tri* always returns a new lazy-seq and
tri returns the same instance of that lazy-seq?
"actually creating" means it's calling the function that generates the lazy seq. Notice the parens. If you do
(def tri tri*), then that would be binding the function to another name, but that's not what it's doing.
(def tri (tri*)) is actually running the
tri* function, and the result of running it is being stored in
This chapter is odd, I’m sure I’m not catching everything. I don’t know if I should go very very slow or just start trying the excerises
I haven't read it, but given that it's called "functional programming," I'd recommend "all of the above" 🙂
I have a bit of pseudo-code I use to express kind of the "zen" of functional programming...
10 LET X = 5; 20 PRINT X;// <== prints "5" 30 X = X + 1; 40 PRINT X; // <== prints "6"
So from line 20 we know that X equals 5, and from line 40 we know that X equals 6, so from line 30 we know that 5 equals 6.
When you read that and say, "Wait, WAT??" you're smacking head-first into the difference between functional programming and imperative programming.
One way to look at it is that with imperative programming, every variable has two dimensions that you have to know in order to get the value of the variable: its name, and its time.
If all you have is the name ("X"), then you can't really know the correct value of X because it's different on line 20 than it is on line 40.
You have to know it's name, the value it has at different times, and what the "current" time is. So really, it could conceivably have an unlimited number of values, according to what time it is.
Functional programming is more mathematical, and the thing about math is that in general you're solving equations in which time is not part of the problem. For any one value of X, there's only one value of sin X, for example.
You don't have to worry that the value of X somehow changed between the time you said "X" and the time you said "sin X"
Yes, that seems like a wonderful thing and it feels like part of the pitch to try clojure and FP in general
Also, … in a lot of my programming experience due to the problems I’ve needed to solve, I just smashed data around. Now looking back, I wonder if making all those data-object-classes was needed
So the brain-bending part of learning FP is learning how to see functions as descriptions of the "timeless" relationship between values as opposed to seeing them as imperative recipes for beating things into some kind of desired shape.
but yeah, I'd say, read slow, try the exercises, and be ready to back track and re-read things as individual concepts become clearer
thanks. Yeah. I’m on my second reading of this ch. Now I see how the program continues without looping. Basically it’s always the last call in each function that moves you along. But I don’t follow how the board is getting manipulated. I’ll keep going. It’s day two on this ch. 🙂
Yeah, they stay in memory, and they'll eventually bite you if you leave them (aka "holding on to the head").
They get garbage collected when there are no longer any references to them, but in the
tri/`tri*` example, the
tri var is always pointing to the first item in the lazy seq, so it will never be gc'ed
and the first item in the list is the "head," hence the expression "holding on to the head"
so, that’s a reason why you’ll need to use
let,.. to have local variables when needed