HN user

leafboi

-4 karma
Posts0
Comments193
View on HN
No posts found.

Great analogy, but analogies can be deceptive, because while the snail can coexist with the tiger, for every two animals that coexist hundreds still have to fail the natural selection process.

We like to view the world through an idealistic narrow lens of an analogy but the truth is often far more complex.

I would go further to say that analogies and quotations are dangerous and deceptive. These quotations don't actually offer any new information. You usually only like analogy because you already agree with it, no new information or insights are being offered other than the comparison that is part of the analogy itself.

Please. There's nothing wrong with my ego. I'm not bragging about anything. I am simply explaining to you my reasoning.

I think you need help with differentiating. I know some good therapists that can help you and can send you some recommendations.

Also it's pretty low of you to ask me to use doctors in place of veterans, doctors save more lives than veterans. Veterans usually have actually killed and slaughtered people including many people of my race and members of my family (vietnam war). You should've told me to use something like lawyers. Your arrogance of telling me to use doctors is off the charts. I wouldn't call it vile, I would call it pure delusion, that or you truly are an evil person for placing people responsible for human slaughter above people who save lives. You honoring people who killed members of my family is not just vile, it's disgusting and morally reprehensible. I don't think you did it on purpose though.

Again you need help. Let me know if you need recommendations for therapy (not a joke).

Project Oberon 6 years ago

I don't think there is nothing in OOP that "forces" you to explicitly mutate state. People just happen to do it that way, even if there was no need for that.

I never said it forces you to do this. Please read my post carefully.

Let me repeat what I wrote. I'm saying that FP and OOP have blurry definitions that people have an intuition about but have not formally defined. Immutable OOP is can be called FP and vice versa. What is the point of having two names for the same style of programming? There is no point that's why you need to focus in on the actual differences. What can you do in OOP that absolutely makes it pure OOP that you cannot call it FP?

That differentiator is setters and mutators. If you use setters and mutators you are doing OOP exclusively and you are NOT doing FP. My response to your post is mostly talking about this semantic issue and why you need to include mutation in your definition of OOP. Otherwise if you don't than I can say all your descriptions of patterns to me are basically FP. You're following the principles of FP and disguising it as OOP and confusion goes in circles.

Please reread my post, I am aware of OOP and it's patterns so there's no need to explain the Factory pattern to me. I'm also in agreement with you like I said.

I am talking about something different: semantics and proper definitions, you likely just glossed over what I wrote, that's why your response is so off topic.

I think you missed my point. I'm saying when you aren't aggressive people tend not to want to intellectually engage with you. People are emotional creatures and what doesn't excite them emotionally they don't engage. I'm saying I used the aggression on purpose for my own ends, but I caveated by saying that no actual attack occurred.

I think you need to think deeper than the traditional "mutual respect" attitude and generally being nice. Not all great leaders acted this way either. It's very nuanced and complicated how to get people to change or listen. The internet is an opportunity to try things out rather then take the safe uncomplicated "nice" way that we usually try in the workplace.

Engage in an intellectual conversion based off mutual respect. You will never change someones mind on the spot, intellectual people will often mull things over for a while. In the process you may learn a few things yourself. I've worked in places that excelled at this, where respectful discourse was promoted. Conversations revolved around facts, but respect was maintained.

Right except this is exceedingly rare. Most people do not act this way. Respect was maintained but the point is instantly forgotten and dismissed. Likely the respect covers up actual misunderstanding or disagreement. I find actual intense arguments open people up to say what they mean rather than cover up everything in gift wrapping.

Think about this way. The reason why Trump won the election is not because he was nice. The complexities of human relationships goes deeper then just "mutual respect" There are other ways to make things move. The internet is often an opportunity for you to try the alternative methods without much risk.

I think the fact we are talking about your tone and not your points about functional programming speaks to this by itself. You weren't heard. You were felt, though.

The world moves through feelings. Not for all cases but oftentimes to get heard you need to get "felt" first.

From a purely structural standpoint there is no risk. But you are talking about something different. You use the word "confusion."

Confusion is an organizational issue that can be handled with social solutions like names, namespaces and things like that. You can compose functions to form higher order functions with proper naming to make sense of things. So for example if you have 30 primitive functions you can compose smaller components into 10 bigger functions in a higher layer and expose that as an api. This is more of a semantical thing as you can still use the lower level primitives as a library and chain those lower level functions to achieve the same goal as using the higher level api, the higher level functions just make it easier to reason about the complexity.

Confusion, Semantics and organization is in a sense a social issue that is solved by social solutions like proper naming, grouping and composing. I'm not dismissing these issues (they are important) but I'm saying they are in a different category.

Overall though the problem I am addressing is structural. There are real structural issues that occur if your functions are not pure. When 4 methods operate on shared state in a class all four methods become glued together. You cannot decompose or recompose these functions ever. They cannot be reused without instantiating all the baggage that comes with the class.

Thanks. But this is the internet. I use a bit of aggression experimentally at times. Overall though, it sounds confrontational but I'm actually pretty factual and I never attacked anyone personally, it's all about the topic and idea. I actually admit when I'm wrong (see above, and who does that in life and on the internet?).

What's going on is I'm spending zero energy in attempting to massage the explanation with fake attempts to be nice. I'm just telling it like it is. Very few opportunities to do this in real life except on the internet.

In the company I work for do I spend time to tell my coworkers that pure functions are the key to modularity when classes and design patterns are ingrained in the culture? Do I tell them that their entire effort to move to microservices is motivated by hype and is really a horizontal objective with no actual benefit? No. I don't. People tend to dismiss things they don't agree with unless it's aggressively shoved in their face. They especially don't agree with ideas that go against the philosophies and and practices and they've been following for years and years.

Thus if I'm nice about it, I'm ignored, if I'm vocal and aggressive about it, I'm heard but it will also hurt my reputation. It's HN feel free to experiment just don't try it at work.

Yeah my attitude isn't the best, but honestly, if I was nice about it, less people would read this or think about it. By doing this on the internet I can raise a point while not ruining my rep. (And I'm not actually aggressive as there are no personal attacks unless someone said something personal about me)

Tell me, in your opinion, how would you get such a point across in a culture where the opposite is pretty ingrained? I'm down to try this, I can repost my original post with the errors corrected and a nicer tone to see the response.

You can't talk about modularity without touching on shared mutable state. Shared mutable state is the fundamental primitive that eliminates modularity. You get rid of this, you're entire program is now modular.

None of the writing really gets deep into this so I assume the author doesn't know.

It's not "mansplaining" you social justice warrior. I don't even know the sex of the author and I don't care. Don't turn this into some sex based conflict. It's called explaining, and that's all it is.

I'm assuming you don't know about it either so I suggest you read my "explanation" as well.

All right. I'm wrong. Didn't know this. Thanks for linking. Still can't exactly fault me on that. It's not easy to find the contextual blog post if this post doesn't easily say it's part of a series.

Still though, my expose is still relevant, those are some hard lines that can easily be gotten rid of if your functions were immutable and not part of a class.

Any internal private function is safe to use anywhere in the system as long as it's not attached to a class and it doesn't modify shared state. If your systems were modelled this way there would be no need to really think about modularization as your subroutines are already modular.

For example:

  class A:
     def constructor:
         //does a bunch of random shit

     def someMethodThatMutatesSomething() -> output




   class B:

       def someOtherFunctionThatNeedsClassA:
           //cannot call someMethodThatMutatesSomethingwithout doing "a bunch of random shit" or even possibly modifying or breaking something else. Modularity is harder to achieve with this pattern. 

versus:
   def somePureFunctionWithNoSideEffects(input) -> output

somePureFunctionWithNoSideEffectsabove does not need any hard lines of protection. There is zero need to use the antics of "deconstructing a monolith" if you structured things this way. Functions like this can be exposed publicly for use by anyone with literally zero issues.

Shared muteable state and side effects is really the key thing that breaks modularity. Everyone misses it and comes up with strange ways to improve modularity by using "walls" everywhere. It's like cutting my car in half from left to right with a wall and calling it "modularization." When you find out that the engine in front actually needs the gas tank in back then you'll realize that the wall only produces more problems.

they use the term breaking down a monolith and "architecture" so from that you can derive that it's literally about using an entire VM or computer to enforce boundaries.

Folders and files are used in "monoliths" anyway. Nothing new to talk about that here. Are you implying that their monolith is just one big file and they're beginning the process of breaking that thing down into multiple files and different folders?

I don't know about you but that doesn't make any sense to me.

I think it's kind of bad that we have this trend to use hardware to enforce modularity. If it's a performance issue, sure break it up into more hardware. If it's just code modularity than by shifting to microservices you are adding additional complexity of maintaining multiple services on top of modularizing the system. In short it's overkill. This whole thing about using hardware to enforce "developer behavior" is stupid. You can use software to enforce developer behavior. Your operating system, your programming language is already "enforcing" developer behavior.

Additionally, your microservices are hard lines of modularization. It is very hard to change a module once it's been materialized because it's hardware.

If you think about it, almost all lack of modularity comes from shared mutable variables. Segregate mutability away from the core logic of your system and the smallest function in your architecture will become as modular as a microservice.

Really, any function that is stateless can be moved anywhere at anytime and used anywhere without fear of it being creating a permanent foothold in the architectural complexity of the system. So if the code is getting to structured where you become afraid of moving things... do this rather than go to microservices.

We can more easily onboard new developers to just the parts immediately relevant to them, instead of the whole monolith.

Correct me if I'm wrong but don't folders and files and repos do this? Does this make sense to you that it has to be broken down into hardware?

Instead of running the test suite on the whole application, we can run it on the smaller subset of components affected by a change, making the test suite faster and more stable.

Right because software could never do this in the first place. In order to test a quarter of my program in an isolated environment I have to move that quarter of my program onto a whole new computer. Makes sense.

Instead of worrying about the impact on parts of the system we know less well, we can change a component freely as long as we’re keeping its existing contracts intact, cutting down on feature implementation time.

Makes sense because software contracts only exist as http json/graphql/grpc apis. The below code isn't a software contract it's only how old people do things:

   int add(x: int, y: int)
Remember as long as that add function doesn't mutate shared state you know it has zero impact on any part of the system other than it's output... you can replace it or copy it or use it anywhere.... this is really all you need to do to improve modularity of your system.

Editing it on the other hand could have some issues. There are other ways to deal with this and simply copying the function, renaming and editing it is still a good solution. But for some reason people think the only way to deal with these problems is to put an entire computer around it as a wall. So whenever I need some utility function that's located on another system I have to basically copy it over (along with a million other dependencies) onto my system and rename it... wait a minute can't I do that anyway (without copying dependencies) if it was located in the same system?

Again and again we pondered: How should components call each other?

I think this is what's tripping most people up. They think DI IOC and OOP patterns are how you improve modularity. It's not. Immutable functions are what improves modularity of your program. The more immutable functions you have and the smaller they are the more modular your program will be. Segregate IO and mutations into tiny auxiliary functions away from your core logic which is composed of pure immutable functions. That's really the only pattern you need to follow and some languages can enforce this pattern without the need of "hardware."

Circular dependencies are situations where for example component A depends on component B but component B also depends on component A.

I've never seen circular dependencies happen with pure functions. It's rare in practice. I think it occurs with objects because when you want one method of an object you have to instantiate that object which has a bunch of other methods and in turn dependencies that could be circular to the current object you're trying to call it from. In essence this kind of thing tends to happen with exclusively with objects. Don't group one function with the instantiation of other functions and you'll be fine.

Still I've seen this issue occur with namespacing when you import files. Hardware isn't going to segregate this from happening. You need to structure your dependencies as a tree.

Project Oberon 6 years ago

I agree with everything you said. To address the part we disagree though:

On one point I disagree: " In both OOP and procedural programming your designs can never have this level of flexibility due in to modules being tied together by shared mutable state."

When I define OOP I define it as mutable state. The main reason is because there's a equivalence when you do "immutable OOP"

  object.verb(parameter)
is no different than:
  verb(object, parameter)
Because both features are equivalent I would say neither feature is OOP and neither feature is really FP.

The difference is (mostly) syntactic sugar and it won't change the structure of your programs overall.

That being said:

  object.setter()

has no equivalence to FP and is unique exclusively to OOP. Even the vocabulary: "setters" is unique to OOP. Hence following this logic, if you're doing OOP your code will have methods and "setters" that mutate or set internal state. If you're doing FP your code should be devoid of such features.

In fact if you do regular procedural C-style programming with immutable variables your code also becomes isomorphic to FP as assignment becomes equivalent to just creating macros for substitution in an otherwise functional expression.

immutable procedural

  def add(x, y):
     doublex = x * 2
     doubley = y * 2
     return doubley + doublex
functional:
  def add(x, y):
     return y * 2 + x * 2
haskell (functional):
  add x y = let doublex = x * 2,
                doubley = y * 2
            in doubley + doublex
also haskell:
  add x y = (y * 2) + (x * 2)


Due to the fuzziness in boundaries there's really only a few things that are hard differentiators between the three styles. When you examine the delineation and try to come up with a more formal definition of each programming style you will find that FP is simply defined as immutable programming, OOP is defined as a programming style that uses subroutines to modify scoped external state and procedural programming involves programming that can mutate variables in all scopes from local, external to global. There's really no other way to come up with hard barriers that separates the definitions and stays in line with our intuition.

It's all semantics either way and most people do a bit of a hybrid style of programming without ever thinking about what are the real differences so it's not too important.

The thing that's sort of bad about OOP is that it sort of promotes a style of programming where subroutines modify external state that's scoped. You tend to get several subroutines that modify some member variable and this is what prevents you from ever reusing those methods outside of that shared state. <= This is in fact the primary area of "bad design" that most people encounter when doing OOP programming... shared state glues all the lego bricks together making your code inflexible to counter the inevitable changes and flaws that you can never anticipate. The other issue is people never realize that this is what's wrong with their program. They blame their initial design as incorrect when really it analogous to saying that their initial lego project was incorrect and they should have glued the bricks together a different way. The primary key to fixing this design problem is to NOT glue your bricks together at all!

While even though you're capable of the above antics in procedural programming... in procedural programming most programmers tend to keep the mutations scoped to within the boundaries of the function definition hence keeping the function reusable. The downside of this is that if you have shared state within the scope of your function it becomes harder to decompose your function into smaller functions because shared state glues all your internal instructions together.

It's easy to see this face in functional reduce. Higher order functions like reduce allow you to break out the function that actually reduces a list while a for loop with a mutating accumulator can not be broken into further smaller functions.

compare the two below:

loop decomposed into two reusable functions (reduce and add):

  add = (acc, x) => x + acc
  m = reduce(add, [1,2,3])

  m => 6
not decomposable by virtue of mutating accumulator:
  m = [1,2,3]
  acc = 0
  for(int i = 0; i < m.length; i++){
     acc += m[i]
  }

  acc => 6

You chose to 1) Use one that has legislation protecting it so as to make your analogy worthless and 2) use veterans specifically as if you deserve to have a title protected like people putting their life on the line.

First off you're a liar. The legislation only extends to people who used it for profit so you can legally call yourself a veteran. You lied to my face or you don't know what you're talking about. Pick one.

Second when does using veterans as an example make me low? It doesn't I just used it as an example to show how it's WRONG. get it? Probably not, people like you are incapable of knowing the difference.

You're twisting it. I never said you called me racist but what you're doing is similar. You're calling out something as insensitive when it is in no way insensitive. I could have use doctor but I chose not to because veterans were the first thing that came to my mind as wrong to impersonate. They have a term for people like you who go around starting wars for infractions that aren't even infractions: Social Justice Warriors. Get off your high horse.

And I'm ok with being called vile by someone with obviously incredibly poor judgement.

It is vile. You're accusing me of something evil and wrong. People who don't take the time to read into what's truly going on end up burning the witch in a witch hunt. Your words are deceptive and have the possibility of stringing along a mob in this manner.

It's not low at all. It is also 100% relevant. It's called misusing titles which is the topic at hand. In some cases it's ok in some cases it's not ok. I have not insulted veterans in any way.

You're just trying to start a witch hunt. Not so far from pointing at me and shouting "racist" for no reason. Doing that is not just low it's vile.

Then for some reason, the SV bubble latched on to "software engineer," without understanding that it was supposed to be a joke.

It started as a joke? I had no idea. Is there a definitive source or initial point where it all started? Link or story perhaps?

Don't call me low that's rude. I find it low whenever a commenter on HN decides to be call someone low simply because they disagree. You're using words to twist my statement as if I'm insulting veterans. I clearly am not, don't try to manipulate others' into thinking that's what I'm doing.

I'm saying that you can't call yourself whatever you want in all cases. I use an extreme example to illustrate that it's not so clear cut. Giving yourself titles doesn't only apply to developers and it's not so clear cut why we can only be so laissez faire in software but not in other certain fields.

I disagree. It's blurry and not so clear cut but certain ranks need to be earned otherwise it's fraud.

For example what if I called myself a Navy Seal and combat veteran even though I'm not? That would be dishonorable and insulting to people who actually risked their lives.

Project Oberon 6 years ago

I've found that FP using function composition or other higher order forms of function like composition mitigates the design problem that you and many others complain about.

Essentially in FP you design your entire program as a single immutable function expression that's made out of a pyramid of layers that's constructed of smaller closed lego like functions composed together. People in the FP world call it the point free style.

The type signatures guide the architecture of your program and can easily be replaced decomposed or recomposed into higher or lower forms of abstraction without compromising your overall program. Design comes naturally like building something out of legos... Easily configurable, and minimal planning or need to hold the entire program in your head. If the design is wrong like legos your program is easily reconfigurable.

The main factor that allows lego like design is immutability. A lego that mutates state outside of its own scope is a lego piece that cannot be modular. FP by making everything immutable makes your program legos all the way down meaning your smallest primitive can likely be broken down further to reuse in other places and recomposed to form other higher order abstractions that are easier to reason about. In both OOP and procedural programming your designs can never have this level of flexibility due in to modules being tied together by shared mutable state.

Of course there are costs to immutability: both low level costs such as memory management and high level costs such as graph algorithms that require mutability to be effective. There are ways to deal with these issues but they are not trivial. In the end all FP programs must "cheat" in some way and have a small portion of their program actually mutate something.

Overall though, in all my years of programming I have found FP to be the best overall answer to the design problems that most programmers run into. It's by no means a perfect answer but it is the best I've seen and unfortunately not applicable to all domains.

It's a higher order composition of functors. Lack of Commutativity still applies and is the factor for why the codomains aren't equal not associativity. It's all pedantry though. Overall you're right.

Intuitively the composition is similar enough to function composition that is has the same basic ruleset and is how I'm working out the logic in my head. Think of the functor as a tuple of the accumulator and the value: (acc, x), and the function is just an op that takes in this tuple as a parameter and spits out a new tuple (acc, z) with the next value in the list.

I addressed it earlier here: https://news.ycombinator.com/item?id=24449271

Function composition is associative but not commutative.

So in essence given three functions z,g,f and composition operator <.>

   f . g . z != z . g . f (commutativity)
which is sort of what fold left or right is doing (but with z g and f being the same function).

but:

   f . g . z == z . (g . f) (associativity)

My edit is right about the operations not being commutative. Parent is wrong about associativity as it has nothing to do with this, but he is right that the codomains of left and right are not equal.

Function composition isn't completely accurate to what's going on, it's a more higher order form of composition going on with fold but the rules remain the same.

Whatever, either way, Overall I'm wrong

Elements in sets are not ordinal. In principle they are the same as the set (B, A) is the same set as (A, B).

If you're saying that foldRight in scala exists aesthetic reasons... well can't argue with that. I figured it was more for legacy reasons as the original poster said that there use to be a performance difference.

As for the associative thing I mentioned side effects. Function composition is always associative. Unless you have side effects. See: https://www.wikiwand.com/en/Function_composition (search for associative)

I don't know much about crypto but I'm assuming you're referring to things that aren't side effect free. In general though a hash function should be associative under function composition as it is just a surjective mapping from domain to codomain.

Also can't exactly read that syntax nor the stuff below it. Not a scala dude. Maybe a more traditional map implementation in like python or JS pseudo code would make more sense to me, but that may be too much to ask.

edit:

I think you actually may be right. We're both a little wrong with our reasoning though. Function composition is not commutative. And FoldRight and FoldLeft reverses the order of composition which has an effect on operations that are not commutative.

There's a real performance downgrade when performing in front of people. To add more accuracy to your assessment I would give these people the opportunity to perform in a room without someone watching.

Another thing to consider is even if you interviewed that many people there's really know way to evaluate your interview accuracy and performance unless you work with all 100 people.

Assuming the data structure is a singly linked list than yes it's not stack safe.

At a high level foldLeft and foldRight represent abstraction leakage. The Domain and Codomain for both functions are exactly the same. If there is no performance difference or side effects to consider then there is almost no point in having two fold functions as a plain fold has the exact same inputs and outputs as foldLeft or foldRight.

Typically for side effects you don't want to put it in a fold as you're integrating way too much IO with your functional computations. Rather functional languages tend to have something along the lines of "foreach" for using side effects on the content in a functor. That being said it's strange that scala has a foldLeft and a foldRight with identical performance characteristics. Maybe it's a legacy thing. I dunno, not a scala guy.

Just bringing that up. I still agree with you that the interview question sucked and that the interviewer was wrong. Personally I wouldn't have ever figured out that was what the interviewer was looking for even when I do possess the requisite knowledge.

One question I would ask you is: what is _similar_ about them? Could you express all of these with one abstraction? Is there a difference between choosing `class` as the base abstraction, vs a closure?

The answer is yes you can. But you're thinking in the wrong direction.

First let's make things clear. A function is just a one line expression where all values are immutable. There is no concept of time or procedures in a function.

function

  def f(x):
     return ((x + 1) * 2)/3

procedure:
  def f(x):
     x = x + 1
     x = x * 2
     x = x / 3
     return x
You are saying that a procedure is isomorphic to an object which is to say you can define an object in terms of a procedure and a procedure in terms of an object. People often mix up the two terms, procedure and function but it's no big deal. The issue is, you used the term "Higher Order" function and the second issue I had was that it's actually quite an obvious thing presented as if it was novel.

Well first off all computers are procedural machines. The underlying machine is just executing machine code which is a series of procedures. So all programming languages on top of this are implemented with procedures.

That means OOP languages are implemented with procedures.

That means FP languages are implemented with procedures.

That means procedural languages are implemented with procedures.

Basically your post is just reiterating how an object is implemented by a compiler.

However the title of your post used "Higher Order Function." This implies you don't know the distinction between procedures and functions as "Higher order" functions are usually reserved for true functions, not procedures.

That was the point of my post, to help you see the distinction because although you can create objects from procedures, you cannot create objects from functions because objects require mutation which is a primitive that a function cannot actually provide. The relationship is surjective or unidirectional.

harder to learn new things this way, and unless you are almost finished with your career, it can be detrimental

This is the internet. I can communicate without a filter on the internet with little consequence. Filters slow things down as do a lack of filter. Either way I can get to the point quickly without worrying about offending someone.

There's nothing for me to learn here other than domain theory which is very advanced math and how people behave.

If you follow the conversation you'll see that the entire argument turned into a battle of definitions with me turning to a very generally accepted definition of a function and bitdizzy turning to using more obscure mathematical definitions of "function" and arguments about semantics what context is relevant to what definition of "function." Whatever definition you choose to believe domain theory looks like very advanced stuff and clearly outside the scope of your average technical conversation.

Either way, I didn't have time to respond to your other comment below. But I will now.

Don't worry about the upvote thing. It's just for this thread I can switch accounts.

No you should just stop voting me down. I'm literally going to go negative soon, I just joined. I literally cannot talk to you if you continue voting me down. It's bad form.

I think you should look into domain theory it is one of the most celebrated discoveries pertaining to the semantics of functional programming languages. And maybe you'll understand that from a programming point of view, what a function is is much more flexible and subtle than you think.

Sure I could. But "context matters." This is not the topic of the conversation. There's a level of depth we're operating at here. Very few people understand "domain theory" and you shouldn't assume as much when you communicate with anyone.

I don't take wikipedia to be authoritative about anything but I'll bite.

No but it's more authoritative than a random person on the internet (you). For things like this it's good enough. I'm not writing a paper here.

Well, obviously in this context the author of the submission wasn't using that definition.

Context matters.

In most mathematical settings it would be a perfectly fine definition, but not here.

In this context it's also perfectly fine. OP did not make a distinction between subroutine or function. He also uses the term higher order function wrong. It shows two things. He does not know what a higher order function is and he does not know what a function is.

Here are the problems with it: It assumes an interpretation in sets when there are a plurality of interpretations of functions qua functional programming which are not compatible with set theoretic models. For example, functions in homotopy type theory have higher dimensional structure than just being elements of a set. Functions in domains have more structure than just the extensional mapping from inputs to outputs. Your chosen definition also includes non-computable functions which are simply not admissible in this context.

This is the garbage pedantry that I warned you about earlier. I'm choosing the generally accepted academic definition. Hopefully you're not one of those people who can't comprehend "generally accepted" without an expose into axioms and different obscure branches of math.

You seem to be confused by the existence of multiple definitions and how they are appropriate in context.

Find the generally accepted definition in wikipedia that this person is using (Hint: no actual technical definition exists). Obviously he's using "function" in place of procedure or subroutine. But then he uses the term "Higher Order" to imply an actual functions instead of procedures.

Not only does he use "Higher Order" incorrectly but his usage of the term indicates he doesn't know what a function is and the difference between a function and a procedure.

Yeah I'm not going to reply to your shit any more. HN really needs to change the policy of not letting parent posters vote others down.