I’m something of a stream of consciousness programmer: I have a thing: fold, then spindle and finally mutilate it. Or: I want to do do this n times, so I’ll use a loop and do this stuff in it. And I like to code as I think. Of course, I make a horrendous number of errors but that is what I love about computers; the compiler will catch a bunch, the program crashes, you fix it, repeat until it works. No animals are harmed, you don’t have to throw away a half a sculpture and start over. (Of course, if you do nuke plant controls or flight systems, you live in a different world and don’t hire programmers like me.) So, I like the noun/verb/verb… style languages, which tend to be OO (as opposed to verb/verb/…/noun). An example is “abc”.toString(16).println() which converts a hex string to an int and prints it. Compare to println(stringToInt(“abc”,16)). How you think about and formulate a solution will determine what works best for you.
Given that, OOP typically breaks down when you have to intermix methods and functions (ie things that are not a part of the object you munging). To me, those are “halting” moments that break the flow: foo.method.method, ah crap, what I want to do isn’t a method, back up, restart: f(foo.method.method …).
Another example: I want to create a function from some VM code. Actually, I want to create some functionality (add 1 to something) and wrap it in a function so I can pass it around (ie create a lambda the hard way). So I’ll create the code:
code := Compiler.Asm.asm(“Int(1)\nsetX\narg0\nadd\ndone\n”);
and then create the function wrapper:
f := self.fcn.build(T(“f”,”n”),code);
and test: f(5) –> 6, f(“foo”) –> “foo1”. All fine and dandy but why in the world do I create the used-only-once code variable? Because I don’t think “to create a function, I create a function shell, then create some code, then …” as in
f := self.fcn.build(T(“f”,”n”),
(it might be different if I could create the function shell and then add the code but I can’t).
What to do? Swipe an idea from functional programming: function composition. Not as in currying or creating an actual function of the composition, just as a syntactic device. (I’m sure other programming paradigms have done this, but FP is where it stuck in my brain). I use a colon (“:”) to compose two chucks. The second example becomes:
f := Compiler.Asm.asm(“Int(1)\nsetX\narg0\nadd\ndone\n”) :
with the “_” showing where to put the code. Nice, the code now reflects my thought process (for better or worse). Or even:
self.fcn.build(T(“f”,”n”),_) : f := _;
I can now use the colon as a “fat” dot to build a left to right stream of actions to an initial object.
Another simple example:
List(1,2,3).xplode():String(_):List(_) –> L(“123”)