Hacker Newsnew | past | comments | ask | show | jobs | submit | leafboi's commentslogin

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.


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.


>>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?

This entire post is literally about using folders (directories) and files to enforce boundaries...


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.


Hey Leafboi - I recommend reading the first post in the series for some background https://engineering.shopify.com/blogs/engineering/deconstruc...

We don't use "hardware" or "VMs" to facilitate modularity.


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.


I think what's really unfortunate here is you started pretty pointed in what you were saying, and you've stayed pointed. It reads as confrontational.

It's unfortunate because you make a good point. Pure functions do not get the attention they deserve. However, no one will read that because you just sound like you're attacking for no real reason.

I'm only saying this because if you're this way here there is a solid chance you're like that in other areas of your life. What you have to say is important, but if you approach your conversations this way people won't listen.

Why did I take the time to write this? Because sometimes those closest to us won't give us the feedback we need.


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.


I appreciate the point you're trying to make, but the truth is that you can make factual arguments without being so aggressive. Whether the aggression is targeted at a person doesn't really matter. It's unnecessary, disrespectful, and just feeds into the general toxicity that plagues our culture.

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

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.

> I'm not actually aggressive as there are no personal attacks

Aggression without a target is still aggression. If I aggressively take the recycling out, that aggression is still experienced by people around me. Probably my partner, who will inevitable have a little talk to me about it, lol.

> Tell me, in your opinion, how would you get such a point across in a culture where the opposite is pretty ingrained?

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.

Sidebar: Shopify doesn't really have microservices. They have a few services, but they are entire services which serve an entire business unit. They are the exception. When I worked there I worked on one such service. What I'd tell people is if you couldn't start a whole new company with the service you were building, don't build it as a service.


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.


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

This is true, but you have options in terms of what feeling you're aiming for.

There is a world of difference in the response you're likely to get from "When Z you should do X because Y" vs. "We had a Z problem, it turns out that Y was the issue, so we did X."

The former will probably get you an "uh-oh" and the latter an "a-ha" or "hmm". Big difference.


Just because a function is pure doesn't mean there is zero-risk in exposing it publicly. You're conflating complexity in managing state with complexity in managing domain boundaries.

A tangled web of function calls can be very confusing to work with, regardless of purity.


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.


I don't think you need to mansplain architecture to the blog post author.


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.


How would you properly learn this craft? What resources would you recommend or look into?


K. Cooper, L. Torczon "Engineering a Compiler", 2nd ed. (2011)

A. W. Appel, M. Ginsburg "Modern Compiler Implementation in Java" (2007)

S. Muchnick "Advanced Compiler Design and Implementation" (1997)

The last book focuses entirely on program analysis and optimization. It even has a chapter on optimization for the memory hierarchy! Of course, since it's a rather dated book, the specific details in that chapter are mostly useless today, but the rest is solid.

However, those books mostly cover imperative languages (although Appel & Ginsburg devote a chapter on functional languages, both of strict and lazy variety and discuss some optimization challenges), so if you want to learn about implementing functional languages...

S. L. Peyton Jones et al. "The Implementation of Functional Programming Languages" (1987)

A. W. Appel "Compiling with Continuations" (1992)

Holy fatcats, those are some old books! But sadly, I am not aware of more modern ones. Try searching for papers on the topics that interest you in particular, I guess (for example, there are several papers that discuss appropriateness of using CPS as IL: "Compiling with Continuations, Continued", "Compiling without Continuations", and "Compiling with Continuations, or without? Whatever". Yes, the puns seem to be the noble tradition in the PL implementation circles). The first book starts as a general introduction but starting at about the middle firmly steers into implementing a lazy languages. The second is pretty much a description of how SML/NJ compiler was made, based on its state in about 1991, of course, and has some interesting benchmarks on efficiency of different implementations of closures.

Plus, there are lot of random pages on the web with resources for various compiler implementation courses from different universities. For one arbitrary example, https://course.ccs.neu.edu/cs4410/


https://craftinginterpreters.com/ is a good intro book.


Probably LLVM. You just have to parse the syntax into LLVM IR


If your language is fairly low-level, you might be able to get away with "translating" it into LLVM.

If it's not low-level, you have to make a bunch of implementation decisions - how do your language's killer features work under the hood??

For just one example, for V, the author reuses Go's `go` keyword to launch a new coroutine/green thread. What algorithms do you use to share work between threads equally? What data structures do you use to represent those? What's the right balance between latency, throughput, memory usage, etc etc?

Many common language features are non-trivial to implement, even with the help of the LLVM IR (which I think is wonderful).


Dragon Book probably still valuable resource.


It should be noted though that Dragon is very detailed especially on parsing. Thus some consider it a bad introductory book and/or even outdated. But it's good resource if you want to become better and parsing is just a part of the book.


The Dragon Book used to be a good recommendation but not anymore. It is outdated.


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.


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

Like all the "engineers" on HN who are really just programmers. There's a word that's been bastardized over the last three decades.

It used to be a common joke: A garbage man is a "sanitation engineer." A housewife is a "domestic engineer." A farmer is an "agricultural engineer." Then for some reason, the SV bubble latched on to "software engineer," without understanding that it was supposed to be a joke. Maybe they felt bad because they had to work with electrical engineers.

I ran into a guy in a bar once who introduced himself as a "software engineer." I asked what engineering board licensed him to use that title. He said none, but that he's an "engineer" because he designs complex systems.

Structural engineer = engineer. Electrical engineer = engineer. Architectural engineer = engineer. Guy who pushes buttons = programmer.

California state law defines engineer: "consultation, investigation, evaluation, planning or design of public or private utilities, structures, machines, processes, circuits, buildings, equipment or projects, and supervision of construction"


Programming and Software Engineering are two different things, and I'll challenge anyone that says otherwise.

Why? Because the ability to program is a subset of what a software engineer needs to be able to do. Granted, it's an IMPORTANT subset, but to create, or "engineer" good software on any truly useful scale, one needs other very, very important skills.

Engineering is based on the idea that you are using some degree of scientifically sound principle to create something in practice. That applies to creating software. There are clear, scientifically rigorous axioms, corollaries, etc that dictate ways that software can be written effectively, from the basic instructions a computer can process all the way up to the highest levels of abstraction. Software standards are developed that define ways that software should be written to take advantage of this scientific resource, and a huge part of writing effective and useful software is managing how one spends their time creating, refactoring, testing, and deploying/publishing that software. That is NOT an easy problem, and it is distinct from programming in and of itself.

The idea that a "board" has to exist to say whether or not something is an engineering practice doesn't hold water because it's the science underpinning the practice that makes it engineering.


>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?


Is there a definitive source or initial point where it all started? Link or story perhaps?

It's pre-web. No links. You had to be there.


Software engineers used to be able to get licensed. I think in Virginia the last time it was applicable was 2011.


...also a bit insulting to all the innocent victims in some poor countries.


It would be a federal misdemeanor, not just "dishonest" which is why the analogy sucks. Going to compare yourself to a veteran to make a point about developers is pretty low.


> It would be a federal misdemeanor

Not quite. Stolen valor can only be charged when it's provable that the person in question benefited in some way, usually financially, from the lie.

Don't get me wrong, it's a dickish and incredibly disrespectful thing to do, but it isn't illegal in and of itself.

Edit: IANAL, but I've read a good bit about this particular subject.


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 didn't fall it low because I disagreed I called it lo because you jumped to a low analogy.

And you using a legally protected status to talk about developers is not relevant and a poor analogy but ok. You using veterans is low.


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.


You could have used doctors, or some other title. 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.

And then when confronted on it, you're now accusing me of "Starting a witch hunt" when in fact I just called out your actions directly. I never called you racist - you're bringing up nonsense to pretend you're virtuous when you're not.

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


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


The ego is out of control.


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


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.


Agree FP is great as you exposed for a large category of tasks. Agree it is not suitable for some fields, and hence, not a panacea.

FP offers a better syntax for most of the programs I write, hence it makes the initial effort easier. Especially "compiler like" or "interpreter like" programs more often than not just fall into a pit of success.

But still - my original point remains. I am unable to design a program beforehand. The iteration is just faster with FP.

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

There is nothing that stops one from writing most OO or procedural programs using immutable style. In fact, this style makes those programs better as well. Just try it. Never mutate an object. Each method, if they must mutate something, then let them return a new object instead.

This style is not applicable everywhere, and due to lack of garbage collected immutable datastructures in the C++ basic library, for example, the area where immutable style can be used is smaller than in a FP language.

And you can't use it in those cases naturally where you actually need to mutate existing storage. But, say, an array of 10 elements? Immutable! Most strings smaller than n * 1000 chars? Immutable! Etc.


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


Again we disagree :)

"if you're doing OOP your code will have methods and "setters" that mutate or set internal state"

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.e. instead of mutating an instance of class Foo

void Foo.set(Some bar)

There are several patterns that make instance of Foo immutable. As an example:

1. Use just 'Factory' pattern to build state and disregard mutation altogether FooFactory fact; fact.AddBar(Bar bar); Foo foo = fact.build();

This may appear as mutating (the factory) but the point is the mutations are located at the factory, which is expceted to have a limited scope, and the entity with larger scope (Foo) is immutable wihtout setters.

2. If there is need to modify existing state, instead of mutating the instance, return a new instance with the value modified. So instead of

void foo.Set(Bar bar)

Use method that creates a copy of foo, modifies state, and then returns a new instance of Foo

Foo foo.Modify(Bar bar)

Just removing mutability actually goes long way in making programs more legible akin to functional programs.

I agree functional style is often the best. Unfortunately we just don't have a functional language that could replace C++.


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


> That being said object.setter() has no equivalence to FP and is unique exclusively to OOP.

What about Lens.Setter? (http://hackage.haskell.org/package/lens-4.19.2/docs/Control-... )


That's not mutating anything. It's not a true setter.


But maybe it’s a true scotsman..?


The hard truth is that all the changes you made have little impact. The worst case scenario for species and the environment is pretty much on track to play out. But we don't like the truth do we? I see myself getting voted down for this.


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.


> The Domain and Codomain for both functions are exactly the same.

This is not true.

> def List[A].foldLeft[B](z: B)(op: (B, A) => B): B

> def List[A].foldRight[B](z: B)(op: (A, B) => B): B

Notice the signature of the fold op: the arguments types are swapped. This is because fold left and right on a list [a, b], say, is the difference between:

(z op a) op b

and

a op (b op z)

(If this isn't compelling enough, consider [a, b, c].) Not all functions are associative. For example, consider a cryptographic hash function.


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.


I don't think I understand the point you're making. I just tested it, and empirically your assertion is incorrect:

// this makes a linked list ten million and one elements long, from zero to ten million

val longList = (0 to 10000000).toList

// this adds the elements

longList.foldRight(0)({ case (l, r) => l + r})

This does not stack overflow.

You write:

>> a plain fold has the exact same inputs and outputs as foldLeft or foldRight

but if you use fold over a collection of type T with the fold function in Scala, the result must be of type T. Fold left and fold right don't have this constraint. Further, this fold is only coherent if the operation is commutative, because it doesn't happen in any particular order. You can add integers in any order to make the same sum, but you can't add pages of a PDF in any order to make a PDF.

Framed via recursion schemes, I'm pretty sure foldLeft can be viewed as a catamorphism where foldRight is an anamorphism. You're consuming the tree from different directions. They may have the same domain and codomain (I'm a little hazy on that) but they're not apparently the same function. y = 2x and y = 3x both have the same domain and codomain, right? But the difference between them isn't aesthetic.


Parent wasn't slightly wrong, you just tunneled in on the signature of the operator function, when the reason why parent comment brought it up was to illustrate that the operator function is not necessarily associative, and that the function signature was meant to suggest the difference in associativity.

You're wrong about the operations possibly not being commutative; as you pointed out, whether the parameter list is (A, B) or (B, A) doesn't really matter, so it doesn't pose a problem.

An example is the subtraction operator: with just two elements, I can change `(a, b) => b - a` to `(b, a) => b - a` with with no difference in result. But there is no way I can write a subtraction function for foldLeft that gives the same results as a foldRight on subtraction in general. That is, I can write op such that a op b = b - a, but not that (a op b) op c = (c - b) - a. Nevertheless, I can still write op such that a op (b op c) = (c - b) - a due to some dual notion of commutativity.


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


But sincerely, thanks for commenting. If I'm walking around self righteously asserting incorrect stuff I much appreciate people pointing it out


You're right.

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

> it's a more higher order form of composition

More precisely, a fold performs function composition on the provided operator curried with the respective elements, so that z g and f above are different functions (hence not commutative in general, but associative in general, wrt folding).


> Function composition is always associative.

You're still confused. There is no function composition here.

op in the example above is just some other function, like +. The associativity of + and function composition are true for totally unrelated reasons. Associativity of plus is an inductive argument that follows from the Peano axioms.

Function composition says:

(f o g) o h = f o (g o h)

as functions. It is true because unary function application "serializes" function applications. Formally, I mean:

    ((f o g) o h)(x)
      = f(g(h(x)))
      = (f o (g o h))(x)
Function composition has one value flowing through several functions. Fold has several values flowing through one function.


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


Ok. No. There's a lot of confusion with semantics. Following the most used definition of OOP as defined by JAVA, C++ and C#:

Classes are in no way functions in the FP sense because classes mutate state.

Classes are in no way functions because calling methods requires the instantiation of unrelated state. Example:

   class A
       def __init__(self, a, b, c):
          self.a = a
          self.b = b
          self.c = c
          self.banana = create_banana(create_gorilla(create_jungle()))

       def process_a(self):
          return process(self.a)
process_a cannot be used unless a, b, c and the banana plus the gorilla holding the banana and the entire jungle the gorilla lives in is instantiated.

Let's talk about terminology. There are three that often get mixed up.

   Procedure = a set of instructions that could encompass mutating and changing state.
   Function = a box that when given input produces an output. The box cannot modify the universe. It can only produce something new when given an input. 
   Object = A grouping of a set of procedures and state that can mutate. 
The javascript programmer OP is mixing up function and procedure. He defines a procedure and says that it can be a class. A procedure can be a class as it's just a set of instructions which can encompass defining scope, state and more procedures restricted to scope and state (aka an object).

This thing right here, written by the OP:

  function setFirstName(firstName) { 
    fName = firstName
  }
Is not a function... it is a method or a procedure that mutates state.

A function can do none of the above.

That's it.


You're making an argument from definitions that would exclude ML from being a functional language, which is absurd.


No I'm using the mathematical definition of a function. ML is not Math nor is it purely functional.

All functional languages need to bend the rules a bit in order to have side effects but in general the person is not writing functions and therefore is not getting the benefits of using functions.

FP is about reducing and restricting these functions that break the rules. Defining a class in terms of mutations and side effects is going against the philosophy of FP.


> No I'm using the mathematical definition of a function.

Which mathematical definition? A "box" is not a mathematical definition. There are multiple mathematically precise definitions of "function" possible. Yours is none of them. Some of them accommodate objects that model mutable state.

I don't think many (any?) PL theorists or functional programming practitioners would agree with your dogmatic stance. Where are you coming from with all this?


[dead]


You have missed the point.

It’s curious you think this piece is written by a “JavaScript programmer”, and the person who responded to you here is a “junior” — the implication being that you know more.

It might help to take a step back and assume intelligence in others: what if these people are smart? What could you learn from them? If you think the idea is wrong, assume it’s coming from a peer. One way you know you are doing that, is if you form your disagreement as a question.

I took the time to respond to you, because it looks like you have some real love for programming, but know less than you think. You can grow a lot more if you shift some of your thinking


>You have missed the point.

Tell me what you think the point is. Typically when someone thinks a point was missed they address the point rather than devolve the conversation into a condescending description about my character and how I should act. It's a sort of tactical what you're doing here. But who cares, no one is reading.

It's curious how you don't even address my points and just say that I missed the point when I'm the one dictating the point in my original comment. Typically this isn't how you respect other people and get them to respond positively to your comments, what you're doing will draw other people to support you but anger your target because of the condescension. I'm not sure what you're objective is because people aren't really reading this thread... it's already buried.

>It’s curious you think this piece is written by a “JavaScript programmer”,

The examples in the original piece are in javascript. Why don't you RTFA before commenting on the "point."

>and the person who responded to you here is a “junior” — the implication being that you know more.

The Junior thing was more of a retort. I said it with full awareness of what it implies and how the other person would take it because his tone obviously implies that he doesn't think he's a junior. Basically the replier has his own opinion which he is entitled to say (and that I respect) but when you say things like "dogmatic" and then vote me down... that's just not respectful. Since I can't vote him down I inject a bit of subtle rudeness in my replies as a subtle retort in return. Just being a mirror. Similar in a way to the subtle game you're playing. That's all this is.

>It might help to take a step back and assume intelligence in others: what if these people are smart? What could you learn from them? If you think the idea is wrong, assume it’s coming from a peer. One way you know you are doing that, is if you form your disagreement as a question.

Maybe you should take a step back and look at your own post. Telling people to shift their thinking implies you have a sort of superiority complex. As if you're not the one that's mistaken. How do you know I'm not a peer? How do you know I'm not superior. Perhaps you should take a look at yourself. You seem like a guy who thinks he's superior to me in programming but you haven't demonstrated as much, you haven't even addressed the point.

You went on a side tangent talking about my behavior. Trust me, if you want someone to change or listen to you, talking to them like this is not the path.

You want to know what will make people respond to you and listen to you? Address them without any subtle disrespect. It's very simple.

You could've responded to me like this:

   I disagree with you. I also think there was a misunderstanding of the point. Here's why...
By proving the other person wrong without being disrespectful you can change the other person's' character. But obviously this isn't our objective here is it?

That being said take a look at this wikipedia post and tell me. Who missed the point?

https://www.wikiwand.com/en/Functional_programming

   "Functional programming is sometimes treated as synonymous with purely functional programming, a subset of functional programming which treats all functions as deterministic mathematical functions, or pure functions. When a pure function is called with some given arguments, it will always return the same result, and cannot be affected by any mutable state or other side effects. This is in contrast with impure procedures, common in imperative programming, which can have side effects (such as modifying the program's state or taking input from a user). Proponents of purely functional programming claim that by restricting side effects, programs can have fewer bugs, be easier to debug and test, and be more suited to formal verification.[1][2]"
Literally that's the definition I'm following. It's one form of the definition and certainly a popular one. That's my opinion. You disagree? You think I missed the point? Elucidate. The original poster can disagree but my opinion is far from as he puts it "absurd."

Read the article. What definition of functional programming does that class with a setter even fit under? Ok he redefined it as a higher order function... Is what he doing procedural programming or functional programming. It looks to me he's doing a bit of everything and calling it a function. Does the guy even know that the class keyword is just sugar for "function" in javascript?

Look at this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

Literally it says "classes" are just special functions. He's just reiterating the javascript spec as if it's a new fangled discovery. In fact, before ES6 all "classes" were written with the keyword "function." No dude. The article writer doesn't get it and neither does the person who responded to my post. When you do OOP with LISP you're not doing FP period. The article writer just noticed an isomorphism and is likely amazed by what all JS programmers were doing before ES6. Not to be insulting but the parent poster likely doesn't have much experience.

>I took the time to respond to you, because it looks like you have some real love for programming, but know less than you think. You can grow a lot more if you shift some of your thinking

I too took the time to respond to you. Despite your condescending attitude/game. Let's see where this goes.


If you decide to dismiss a position by saying that it chose the wrong definition, you're not contributing anything useful. "Pure" functional programming is not more functional programming than "Functional programming", the adjective specializes it and makes it more narrow. I don't really care what a wiki article says. I can run a survey of my colleagues if you want?

As for calling me a junior, well, you don't know how much experience I have, do you? It's probably more than you, though. I've used and participated in the development of functional programming languages for over a decade at this point.

Unsolicited advice: Sophomoric pedantry isn't a good look.


>Unsolicited advice: Sophomoric pedantry isn't a good look.

Starting conflict and calling people "dogmatic" and voting people down is not a way to win people over. I can see a number of paths this road could have gone down where you can easily get another person to agree with your ideas as an alternative viewpoint despite a wikipedia article saying otherwise. You chose to take none of these roads, maybe largely because you don't know how to do this.

>I don't really care what a wiki article says.

Right because your opinion is the best opinion and only opinion that matters. The community opinion and the majority opinion has no relevance to you because you participated in "functional development for over a decade." Whoop dee doo. I chose a definition of functional programming that has huge relevance to the community at large. You on the other hand... haven't even stated your definition yet.

Unsolicited advice: Arrogance and the inability to admit your own mistakes is not a good look. A decade of experience does not earn you the right to act like an ass hole nor does it make you a good programmer.


You chose a definition among many and then dismissed the submission as "confused" because it does not meet your definition.

I noted that your definition would preclude ML functions from being called functions. Your response was that ML wasn't purely functional, but that doesn't make it not functional. The pure in "pure functional" doesn't "to the exclusion of non-functional", it is simply a narrower category.

Considering that ML is one of the most impactful functional programming languages both in theory and practice, I think it's right to call that absurd and dogmatic. If you take it as a personal attack that I called your argument absurd, I don't know what to say. Maybe grow a little bit of skin?

> You on the other hand... haven't even stated your definition yet.

I don't need to provide a definition to find a flaw in yours. I did not come into this submission looking to smugly dismiss the topic at hand with my obviously irrelevant preferences for terminology. You did.


>You chose a definition among many and then dismissed the submission as "confused" because it does not meet your definition.

My definition? I quoted wikipedia. A lot of people use "my definition" Basically under "your" definition C++ and go might as well be a functional programming language.

>Considering that ML is one of the most impactful functional programming languages both in theory and practice, I think it's right to call that absurd and dogmatic. If you take it as a personal attack that I called your argument absurd, I don't know what to say. Maybe grow a little bit of skin?

Why grow skin? I literally didn't care. I just decided to call you junior because you were acting like one. It seems like you cared more. I was just explaining to the other guy why I called you a junior. I recognize the attack but I literally don't care, but that doesn't mean I won't respond or address it.

>I don't need to provide a definition to find a flaw in yours. I did not come into this submission looking to smugly dismiss the topic at hand with my obviously irrelevant preferences for terminology. You did.

My Definition doesn't have flaws. Like I said, if I expand it to encompass mutability (as you have) then you can place Go and C++ on the functional pedestal. I haven't used ML but clearly a language like ML only allows mutability as a small exception that's rarely used otherwise there's no point to classify ML as functional.

But let's get back on topic. You literally said that no PL theorist would agree with me. But look at wikipedia. Apparently many do. So you're wrong.


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

> Functional programming is sometimes treated as synonymous with purely functional programming, a subset of functional programming which treats all functions as deterministic mathematical functions, or pure functions.

Well, obviously in this context the author of the submission wasn't using that definition. So you coming in and dismissing the conversation because sometimes people mean "pure functional programming" when they say "functional programming" is clearly erroneous. I know when people make this conflation, often when they're talking about Haskell. When talking about ML, no one would take that synonym. Context matters.

I just looked, you provided a set theoretic definition of functions, the wikiwand one. You chose a poor definition for the topic at hand. In most mathematical settings it would be a perfectly fine definition, but not here. Context matters.

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.

So your definition is simultaneously too restrictive and too lax.

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


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


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

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.

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

Would it help if I pretended that you downvoted me? Every time I see my imaginary internet points I will subtract 5.


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.


Admittedly I downvoted this one: https://news.ycombinator.com/item?id=24438137

Yet again though:

"Random person (you)" "he does not know what a function is." "Yeah I'm not going to reply to your shit any more."

...give a good reason

---

Anyways, leaving this thread. I certainly learned something from it, I hope you did too! : )

I now noticed you're at -1, went ahead and gave you an upvote. Hopefully you can still post, and be a bit more aware.

--

Also, great work trying to explain bitdizzly. Def enjoyed reading your explanations, and will explore some the references you popped in


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.


I'm not downvoting you. I can't downvote anyone. I don't think I have enough points to downvote. If I didn't want to talk to you I wouldn't be replying!


> It's curious how you don't even address my points and just say that I missed the point when I'm the one dictating the point in my original comment.

> Typically this isn't how you respect other people and get them to respond positively to your comments

> The examples in the original piece are in javascript. Why don't you RTFA before commenting on the "point."

I wrote that article, so in effect you are responding to my original comment : ).

Fair that what I wrote was condescending. I purposefully wrote it that way, as a second meta-point: to get you to experience what it feels like when people assume negative, and use words like "Ok, no", "Javascript programmer" (negative connotation), "junior"

With that accomplished, moving on to more civil ground.

> I'm not sure what you're objective is because people aren't really reading this thread... it's already buried.

First, as you can now feel, I was pretty annoyed by your presumptuous tone in your initial comment. Second it really did feel like you had depth and love in programming, but from your comments I intuited some traits that lead to lower potential outcomes. Mainly: jumping to conclusions too quickly (harder to learn new things this way, and unless you are almost finished with your career, it can be detrimental).

> Does the guy even know that the class keyword is just sugar for "function" in javascript? ... Not to be insulting but the parent poster likely doesn't have much experience.

Yes, I do know what classes de-sugar to in javascript, I worked with many of the folks who brought classes to the ES spec.

As you most likely know, javascript classes are a bit of a special case, because JS uses prototypical inheritance. Classes in other languages do not de-sugar this way.

For example: you can see a function as a special `class` with only one method `apply`, or you could see a class as a special higher order function.

> Who missed the point?

The point is, that though functions and classes seem distinct, they are less distinct than one would think. In your comments, you seem very attached to the specific distinctions you've set up with classes, procedures, and functions. 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?


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


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: