The Author Online Book Forums are Moving

The Author Online Book Forums will soon redirect to Manning's liveBook and liveVideo. All book forum content will migrate to liveBook's discussion forum and all video forum content will migrate to liveVideo. Log in to liveBook or liveVideo with your Manning credentials to join the discussion!

Thank you for your engagement in the AoF over the years! We look forward to offering you a more enhanced forum experience.

Mark Elston (133) [Avatar] Offline
#1
In unit 1 you devoted quite a bit of time to building intuition for recursion. However, in the first part of the Unit 1 Capstone you went past something quickly that I have had trouble with gaining an intuitive feel for.

Specifically, you mention that Listing C.1.1 is a 'constructor' for cup 'objects'. However, as I read it all I see is a function that takes a parameter and returns a function that takes a function that is passed that original parameter.

If you can parse that and get an intuitive understanding of what is going on then I tip my hat to you.

I can follow it, sort of. In every case where a constructed cup 'object' is used I have to remind myself that it is really just a function that is expecting a function to be passed to it and that the function it receives will be given the original flOz parameter. I then try to unwind the stack and can sort of see what is going on. But I don't really 'get' it. I don't have a good feel for how to do this in my own code.

At the start of C.1.2 you state that 'we have stored our value in an object'. That isn't really the case. You have stored the value in a function as part of the function's closure.

Until I get that intuition developed I will continue to struggle with code like this - and I will probably not be able to make use of this kind of technique very often in any more complex scenarios.

If you can help build that understanding it would be very helpful.
Will Kurt (21) [Avatar] Offline
#2
So this Capstone is definitely a bit different than the rest, and the original draft has a very famous lisp quote about "objects being a poor man's closure" and vice versa at the beginning (see the parable of Qc Na at the end of this conversation https://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg03277.html). The original draft for this capstone also had a bit more exposition about the history and nature of OOP.

Though we have a pretty standard sense of what OOP means now, historically it has just been about sending messages to objects. The key here is that objects *are* in essence functions waiting for objects. The main point of the capstone is to show that even though OOP and FP are typically seen as opposing ways to view programming, FP is all encompassing enough that you actually can recreate the basics of OOP from just the basics discussed in Unit 1. Both Common Lisp and R have object systems that are essentially more sophisticated versions of what we build in the capstone 1.

I'll look through the cuts we made and see if I can rework them to help add clarity and context to this capstone.

Mark Elston (133) [Avatar] Offline
#3
Thanks. Again, the issue I have is in 'seeing' what is going on so that I can make use of it. I can, after a lot of picture drawing (in my head), and stack tracing, finally figure out what you did. But that is a far cry from really understanding it and being able to make use of it.
Thorsten Deinert (8) [Avatar] Offline
#4
I really liked Unit 1 Capstone, because I read some books about FP in different languages (eg. F#, Elixir, and Haskell), and some stated, OOP behaviour could be "simulated" with FP, but doesn't demonstrate how exactly. (F# is bit off topic in that point).

The Capstone really illustrates the crutial point: how to capture the state of an object in a functional way. Thats done by a closure (which intuitively creates a "snapshot" of the context values used in the function when the function is invoked).

I agree, its a bit "mind-bending" to read the "constructor function", because it doesn't return an "object" , but an anonymous function, that:
1. captures the state, here value of flOz in its clojure ("stores it") and
2. is invoked by any function that operates on a Cup. You have to invoke it with a function that receives the captured "state", an Int here, and processes it somehow. E.g, getOz invokes it with a function that just returns the "state", making it readable to the outside world.

So, the resulting "object" is nothing but an anonymus function, that you can give a function that gets invoked with the state. Probably it would be a good point to show the type signature of that function to make clear what happens. If I got it right, the anonymous function returned ("the object") by cup 12 has the signature
(Int -> a) -> a
and the constructor function cup has the signature
cup :: Int -> ((Int -> a) -> a)
. Please correct me if I'm wrong here.
Mark Elston (133) [Avatar] Offline
#5
Thorsten Deinert wrote:...

So, the resulting "object" is nothing but an anonymus function, that you can give a function that gets invoked with the state. Probably it would be a good point to show the type signature of that function to make clear what happens. If I got it right, the anonymous function returned ("the object") by cup 12 has the signature
(Int -> a) -> a
and the constructor function cup has the signature
cup :: Int -> ((Int -> a) -> a)
. ...


I think this does help a lot. I should have really reduced this to the signature myself to help understand it. Thanks.
anthonyshull (2) [Avatar] Offline
#6
The closures for the cup example are completely unnecessary. It is confusing.

cup oz = (\_ -> oz)
getOz aCup = aCup (\oz -> oz) -- This lambda does nothing!


If you use
 getOz aCup = aCup "whatever" 
you get the same behavior.

It is confusing because you are supposed to pass a meaningless value in order to do something as simple as retrieving a value. As the reader, I was wondering what the lambda was doing. Apparently nothing.

So, maybe an explanation of what closures are supposed to accomplish in this situation as opposed to simple values.

cup oz = oz
getOz aCup = aCup
drink aCup ozs = if contains == 0
                            then cup 0
                            else cup (contains - ozs)
  where contains = getOz aCup


Thanks!
Mark Elston (133) [Avatar] Offline
#7
Anthony, I think you are right in that the Capstone is much more complicated than it needs to be to address the 'problem statement'. However, the purpose is to do more than just that simple task.

The problem I had was that I missed the whole point of the Capstone and tried to follow the 'simple logic' without having the bigger picture of what was being described. In the meantime, there has been an update to the book that apparently includes changes to the entire first unit. I am going back and re-reading the book from the beginning to see if I can get a better picture of the material from the new presentation. Hopefully I won't (again) get lost in the weeds. smilie
Rhywun (27) [Avatar] Offline
#8
I'll admit I largely skipped over this Capstone. It didn't seem to follow from any of the previous material & I was wondering why I would even want to pursue the ideas. Maybe I'll tackle it later!