braveandtrue

https://www.braveclojure.com/
moo 2018-08-27T17:14:17.000100Z

in the functional-programming chapter with pegthing they (defn tri* ...) and later on (def tri (tri*)) many functions refer to tri (without the star). What is the idea behind this?

moo 2018-08-27T17:15:00.000100Z

e.g. this function refers to tri and not tri*

(defn triangular?
  "Is the number triangular? e.g. 1, 3, 6, 10, 15, etc"
  [n]
  (= n (last (take-while #(>= n %) tri))))

2018-08-27T17:19:43.000100Z

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.

2018-08-27T17:22:33.000100Z

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.

moo 2018-08-27T17:32:57.000100Z

thinking java it’s like

if (_instance == null) { tri = tri*}
return tri
?

moo 2018-08-27T17:36:14.000100Z

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.

moo 2018-08-27T17:40:19.000100Z

Is it like this? tri* always returns a new lazy-seq and tri returns the same instance of that lazy-seq?

2018-08-27T17:45:15.000100Z

"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 tri

moo 2018-08-27T17:46:13.000100Z

ah ha!

moo 2018-08-27T17:46:37.000100Z

so the return value of (tri*) is getting bound to tri

2018-08-27T17:46:55.000100Z

That's it

moo 2018-08-27T17:47:06.000100Z

Thank you again man! 🙂

👍 1
moo 2018-08-27T17:47:44.000100Z

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

moo 2018-08-27T17:48:16.000100Z

It’s a bigger “chunk” than other chapters thus far

2018-08-27T17:48:24.000100Z

I haven't read it, but given that it's called "functional programming," I'd recommend "all of the above" 🙂

2018-08-27T17:49:05.000100Z

I have a bit of pseudo-code I use to express kind of the "zen" of functional programming...

2018-08-27T17:50:41.000100Z

10 LET X = 5;
20 PRINT X;// <== prints "5"
30 X = X + 1;
40 PRINT X; // <== prints "6"

2018-08-27T17:51:18.000100Z

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.

2018-08-27T17:52:21.000100Z

When you read that and say, "Wait, WAT??" you're smacking head-first into the difference between functional programming and imperative programming.

moo 2018-08-27T17:53:18.000100Z

The immutable aspect?

2018-08-27T17:53:30.000100Z

Immutability is a big part of it

2018-08-27T17:54:32.000100Z

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.

2018-08-27T17:55:10.000100Z

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.

moo 2018-08-27T17:56:20.000100Z

Yeah

2018-08-27T17:56:24.000100Z

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.

2018-08-27T17:57:53.000100Z

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.

2018-08-27T17:59:28.000100Z

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"

moo 2018-08-27T18:00:21.000100Z

Yes, that seems like a wonderful thing and it feels like part of the pitch to try clojure and FP in general

moo 2018-08-27T18:00:35.000100Z

debugging complex state is so tricky

2018-08-27T18:02:01.000100Z

Yeah.

moo 2018-08-27T18:03:48.000100Z

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

2018-08-27T18:03:54.000100Z

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.

moo 2018-08-27T18:03:55.000100Z

anyways. 🙂

2018-08-27T18:04:06.000100Z

🙂

moo 2018-08-27T18:04:24.000100Z

Yeah, what you said last makes sense

2018-08-27T18:05:25.000100Z

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

2018-08-27T18:05:36.000100Z

and of course feel free to post questions here

moo 2018-08-27T18:07:11.000100Z

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. 🙂

moo 2018-08-27T18:12:03.000100Z

so for lazy sequences, are the parts that are “reified” cached/saved somehow?

2018-08-27T18:25:14.000100Z

Yeah, they stay in memory, and they'll eventually bite you if you leave them (aka "holding on to the head").

moo 2018-08-27T18:26:05.000100Z

as in you need to stop referring for gc to work?

2018-08-27T18:26:15.000100Z

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

moo 2018-08-27T18:26:38.000100Z

I thought tri is pointing to the sequence itself

moo 2018-08-27T18:27:04.000100Z

because there is (take-while (conditions) tri) going on

2018-08-27T18:27:11.000100Z

exactly, yes, but more specifically, it's pointing to the head of the sequence

moo 2018-08-27T18:27:17.000100Z

oh gotcha

moo 2018-08-27T18:27:32.000100Z

à la linked lists

2018-08-27T18:27:49.000100Z

yes, exactly

2018-08-27T18:28:12.000100Z

and the first item in the list is the "head," hence the expression "holding on to the head"

moo 2018-08-27T18:28:42.000100Z

so, that’s a reason why you’ll need to use let,.. to have local variables when needed

2018-08-27T18:29:09.000100Z

Exactly. (def tri ...) is immutable, so it will always hold onto the head.

2018-08-27T18:30:26.000100Z

You're better off with a (let ...) if you think your lazy-seq might ever get too big. You can get away with it here because the peg-board game is only going to realize/reify a relatively small portion of that lazy seq