3 ms·
>Well guess what? That's what's necessary to compose things. That's what your compiler or interpreter is doing behind the scenes. You cannot escape this. How M
by crimsonalucard 7y ago
>Well guess what? That's what's necessary to compose things. That's what your compiler or interpreter is doing behind the scenes. You cannot escape this.
How MANY times have I said that there is a definition of compose that is universal and not arbitrary and not specific to certain contexts. You can escape this.
> It might surprise you to learn that "functions" and "procedures" are literally the same thing as far as the computer's concerned (at most, a "function" might be a procedure plus type information, or it might be a procedure that does its own type checking, but it's ultimately a procedure nonetheless).
Except that I have told you repeatedly that not only am I aware of this. EVERYONE is aware of this. Why are you repeating this same concept over and over again. It feels as if this concept is blowing your mind and that you have to share it repeatedly. I hate to break it to you. It's obvious to everyone.
That being said procedures and functions share a equivalence relation. They are not completely the same. If they were then I could call a procedure just like I can call a function, except I can't. Similar to how all programming languages are turing complete but not exactly the same. They are isomorphic but there are differences that can be identified and talked about. Following your logic there would be nothing to compare among any computer language because according to you everything is exactly the same.
>Composing functions is - when all is said and done - literally what my pseudo-Forth example demonstrated, because functions are ultimately just procedures. Forth literally has no type system (at least not by modern standards), and yet it fulfills the literal actual definition of function composition. But no, for some reason that ain't good enough, probably because you seem to believe that there's no middle ground between clean composition (what a type system actually provides) and no composition at all.
I know what you're doing. Get it through your head. I understand it 100%. No need to elaborate. You are bending the system to imitate functions. You can bend functions to imitate procedures as well. I have said again and again I GET IT. Heck you can bend python to be just like forth and write an entire forth compiler in python. Boom now there's no difference between python and forth and therefore nothing to talk about.
Composition is a property of functions through and through. It is not a property of procedures. You can bend procedures to imitate functions but as I have said again and again and again we're not here to talk about the isomorphism between all programming languages and styles of programming. We are here to talk about differences. Functions Compose. Procedures Do not. Stop telling me they are the same, it's like saying that You can drive a car just like you can drive a hunk of metal. How? by making a car out of the metal... just like how you made forth imitate function composition.
>Nothing composes unless you make up some definition on the spot. Composition is meaningless unless you define what "composed" means in a given context. For functions, they're "composed" by calling one with the other's output. For procedures, they're "composed" by calling them one after the other. For objects, they're "composed" typically by either aggregation or inheritance/delegation.
You still don't get it. What do I mean by making up some definition on the spot? It means that given two primitives that I've never seen before I have to make up a new compose function. So for objects A and B I have to redefine a new compose function composeAandB. For objects C and D I have to make a composeCandD. What about procedures? How do I compose steps 1 and steps 6? well the composeStep1AndStep6 Probably needs to insert steps 2 through 5 in between to get a composition. Or if they shouldn't compose period how will a type system or how will a computer know that these two things can't be composed? It can't be done, you must manually prevent this. Arbitrary definitions of composition the spot, that's what I mean. Custom logic literally all over your code to glue things together creating more complexity on every "composition"
When I say a compose function that has a universal definition I mean One where given primitive A and given primitive B, two primitive in which I have NEVER seen before I can compose the two AND the composition preserves context.
I have two functions one function takes sunlight as brightness levels and outputs energy.
Another takes energy and outputs locomotion or distance travelled.
A :: SUNLIGHT -> ENERGY
B :: ENERGY -> DISTANCE
COMPOSE(g, f) = lambda x: f(g(x))
COMPOSE(A, B) :: SUNLIGHT -> DISTANCE
There it is, a single universal definition. New context is created without the need of redefining anything new. True composition. I observed from your post (unlike you) that you already know the definition of function composition. What you didn't know is how it creates new context from old context.
>Not even the purest of functional languages can truly do that. Ultimately, they rely on actual primitives for data; it ain't functions all the way down. Even purely-mathematical functions need numbers to, um, func.
This is how I know you don't know what ur talking about. Do you know lambda calculus? Where are the numbers in that? There are no numbers. How are numbers represented in lambda calculus? Look it up. You can take a look at the Nat type in haskell or idris. The fact that Int exists is abstraction leakage from the lower levels of the computer. Literally Any data structure can be represented by only functions including Numbers.
>The closest you can get to that is... (drumroll...) Forth, which treats any word it doesn't recognize as a call to an imaginary procedure that pushes the value of that word onto the stack, thus trying its darndest to make everything pretend to be a procedure (and thus composable as such). Unsurprisingly - because functions are just fancy procedures - this concept has worked its way into the functional programming realm through concatenative programming.
Guess what. Procedures are just fancy functions. Your mind should be blown right now. When you do forth programming you're actually programming in Haskell. Understand? The two are one in the same. You really need to understand this that underneath the computer doesn't know about context..... All right I'll stop being sarcastic. Imperative procedures do not compose unless you bend them to compose. That's all.
>Put differently: the "power" you feel when clicking together functions like Lego bricks is possible specifically because of procedural composition; the former is just syntax sugar around the latter.
There's no such thing as procedural composition unless you make it up on the spot for every two procedures you want to compose. Again context is required here. A type checker can't check how to compose two procedures.
You literally just called functional programming syntactic sugar. Literally as if nobody knows that assembly language is imperative. Who on the face of the universe doesn't know this? Everybody knows assembly language is imperative, yet no one is uses the term "syntactic sugar" to describe every language built on top of it, only you. You need to stop and open your eyes and stop advertising the fact that procedures and functions are isomorphic as if it's the greatest discovery known to mankind. It's not, it's universally well known. https://www.wikiwand.com/en/Curry%E2%80%93Howard_correspondence https://www.wikiwand.com/en/Curry%E2%80%93Howard_corresponde...
Everybody knows about the call stack and everybody knows about the heap, so stop with your "revelations"
The "power" you feel when using Forth comes from the fact that you are using forth to imitate the power of functions and your brain is amazed that it can be done with stacks and a pointer (revelation: everyone knows how it works). You need to realize that the functions hold the power and forth is bending over backwards to become a function. Assembly instructions are bad primitives as well, literally we bend an instruction set over backwards so it can imitate functions because that's where the power is.
- crimsonalucard 7y agoAlso check out the mathematical definition of function composition. Note how there are type signatures. Function composition defined without types is incomplete. https://www.wikiwand.com/en/Function_composition https://www.wikiwand.com/en/Function_composition
- yellowapple 7y agoSee the Scheme example in https://www.wikiwand.com/en/Function_composition_(computer_science) https://www.wikiwand.com/en/Function_composition_(computer_s.... Where, pray tell, are the type signatures? Come to think of it, where are the type signatures in the page you linked? You'll notice that said example is fundamentally equivalent to the pseudo-Forth one I provided (except that mine doesn't take an arbitrary number of functions/procedures to be composed, though it's perfectly feasible to just call "compose" repeatedly to accomplish the same thing).
- crimsonalucard 7y agoThe mathematical definition is canonical. It is the one that preserves context. The scheme definition is incomplete and allows for invalid compositions to occur. Forth is not composing anything. Remember that, it is imitating composition through a collection of primitive commands. Composition exists in a function as a primitive. Again no one is talking about isomorphism between procedural and functional languages. Composition exists as a primitive in functional, composition exists as a concept of multiple commands in forth or other procedural languages. Get it?
- yellowapple 7y ago> Except that I have told you repeatedly that not only am I aware of this. EVERYONE is aware of this. Why are you repeating this same concept over and over again. Because you seem to continue to think that procedural composition is impossible even though it's literally the thing that allows functional composition to exist on actual physical computers. That you continue to deny this suggests that somehow you are not in the category "everyone". > You are bending the system to imitate functions. s/bending/using/ s/imitate/implement/ Again: procedural composition is a dependency of functional composition as soon as you move from theory to practice. That's what you don't seem to be getting. You're right that my points are indeed plainly obvious, which makes it all the more interesting that you continue to deny them. It's not a revelation for me at all; it's basic computer science, and you seem to have drank so much of the FP Kool-Aid to have forgotten how computers actually work. > Do you know lambda calculus? Where are the numbers in that? Trying to cite some purely-theoretical concept as "proof" that an actual working system can operate without numbers is not proof at all. > The fact that Int exists is abstraction leakage from the lower levels of the computer. You call that "leakage", I call that "making it actually useful in the real world". A function is meaningless unless it has something to, you know, actually operate upon. > Imperative procedures do not compose unless you bend them to compose. Yes, because executing one thing after the other is "bending". /s That's - again - literally all that's necessary to compose procedures, because - again - whether or not they should be composed is different from whether or not they can be composed. The composition may be unclean, but it is still composition. ---- Since we're at the "let's throw wikis at each other" phase of this discussion, here's some reading material for object composition, which you still for some reason deny is possible despite there being plentiful theoretical and practical demonstrations thereof: https://en.wikipedia.org/wiki/Object_composition https://en.wikipedia.org/wiki/Object_composition Object composition - via aggregation - is also a very widespread concept prevalent even in non-object-oriented languages, including functional languages (tuples are the composition of internal objects, and can be universally composed; cons cells in Lisp (and lists in e.g. Erlang) are the composition of other cons cells and/or NIL, and can be universally composed; etc.). To correct myself a bit, inheritance is not in and of itself composition, though it may be combined with aggregation to make a composed object more useful.