Continued from NodeJsAndHofGuiDiscussion. ["conceptually and syntactically messy" in ways we've already discussed -- for instance, syntactic mess arising from the need for a class definition, which even in the most concise of languages (say, Python) is still heavier than a mere method call as .addEventListener() approaches involve, and conceptual mess arising from the fact that the base Button class itself can never be instantiated usefully as a button, and therefore that it ''isn't'' a button. Redefining methods outside the class is very nice to have, and it's good that RubyLanguage and PythonLanguage provide ways to do it, but it doesn't solve the issues. As for the multiple-handler issue, the GUI framework generally needs to do work of its own when you click a button, plus you need to add your own action, at the minimum; under your approach, do you need to explicitly invoke the method in the superclass to make that work? -DavidMcLean] I don't know what you mean by "heavier". [Read "heavier" as "takes more syntax". Pretty straightforward. -DavidMcLean] * Sorry, I don't see where it's significantly more syntax. * [Really? Even if we ignore questions like instantiation, "class MyButton extends Button { onClick(e) {do some stuff) }" doesn't appear to take more syntax than "myButton.onClick.add(e -> do some stuff)" to you? -DavidMcLean] * In that approach, only a little bit more, but that's not normally how it would be used. And we could tweak the syntax of a language to shorten such, but brevity is not the only factor to consider. * [How ''would'' it normally be used? What do you have in mind, if not what I just quoted? -DavidMcLean] * Attributes, other methods, etc. would be in the same class. We've had this discussion already. * [Yes, I'm aware of that. It's a meaningful difference how, exactly? -DavidMcLean] * It's actually shorter than the "external" approach because the class provides context whereas the external approach has to keep reinventing context for each attribute/method etc. * [Oh, I see what you mean. That's ''possibly'' what happens, I suppose, but the common case for button widgets would definitely be to have a handler only on the onClick event, and things like WithStatement can provide the context of which you speak. -DavidMcLean] * What do you mean by "common case"? The existing industry "habits"? And sure one can fix stuff with "with" etc., but syntax can always be thrown at specific difficulties. * [I mean "common case". A button that does a thing on click is needed more often than a button that does a thing on right-click, double-click, middle-click, or on tapping the Q key while hovering over it. -DavidMcLean] * Example 8462 would be closer the common case, if that option was available. * [Indeed, that's exactly the case I had in mind.] * Okay, what's your equivalent of Example 8562 below? * [Added.] Re: "and conceptual mess arising from the fact that the base Button class itself can never be instantiated usefully as a button and therefore that it isn't a button." -- Please clarify. I don't consider OOP to be about classifying objects, categories, and/or types in some kind of intellectual way; it's primarily a modularization technique, and any mental classification assistance is a nice bonus. The "meaning" is whatever the architect want's it to be. If we need "locks" on some objects/classes per instantiation/inheritance limits for protection etc., that can be added to a language (see DualTypingLanguage), but I don't know what the need is you have in mind here. [My point is that you can't meaningfully instantiate an instance of the Button class, if the only way to attach handlers to a button is by overriding its methods. Any instance of the Button class itself is not actually a button, because it can't possibly have any associated behaviour. -DavidMcLean] I'm still not following you. And I never ruled out ''other'' ways to attach handlers. I'm am just making the most common way easy. [For the first point: The class Button represents a button. If you make an instance of it, with new Button(), the thing you get should be a button. However, if you can only bind event handlers by subclassing it (MyButton extends Button), then making an instance of Button itself, with new Button(), does not give you a button; it gives you a decoration. As for other ways to attach handlers: Correct, you didn't explictly rule them out, but you also never actually presented any other ways to attach handlers and you continually deride the most common approach to doing so. Feel free to propose other ways to attach handlers, preferably that work for multiple handlers. -DavidMcLean] Re: "If you make an instance of it, with new Button(), the thing you get should be a button." -- That's exactly what is happening. I don't see a problem. Subclassing is doing pretty much the same as "new" in the kind of language I'm thinking of (objects and classes are the same thing). Perhaps we need better syntax conventions to clarify that; I'm just half borrowing Java parts to try to make the examples resemble something familiar. [If you make an instance of Button with new Button(), you get a button with no event handlers attached to it. That's not a button; that's a decoration. That's the problem. -DavidMcLean] No, it's a blank button that doesn't do anything. (Or, an error if title is required.) [A blank button that doesn't do anything is a decoration. -DavidMcLean] Well, if you don't want a blank/dud button, then fill it up with stuff. [Obviously. But you can't do that if you have an instance of Button, because you can only attach handlers by subclassing. -DavidMcLean] Well, that's what we want to maintain regimentation of modules. Example 8490 shows a possible way to allow "externally defined" classes, but I'm not sure it's wise. I'm not sure I want to try to compete with your scatter-shot techniques. This is dicey territory. [We "want" it to be meaningless to instantiate instances of the base Button class? Why? How does it "maintain regimentation of modules"? -DavidMcLean] I'm not sure what you are getting at. It seems you are used to doing it a certain way. Java's rigidity has perhaps boxed in thinking. Incidentally, if we wanted to programmatically prevent an "empty" instance, then we could have a language with "required" key-words etc., just like in CRUD-land. [I'm not a Java user; its rigidity has had no impact on my thinking. I don't see why it would be useful to provide a Button class which can be instantiated if doing so cannot produce a useful instance. How does it "maintain regimentation of modules" to do this? -DavidMcLean] How is that different than forgetting to hook a HOF to a button? I don't get your complaint. [You can create a button instance, assuming you have .addEventListener()-style methods on the class, which has no event handlers. However, that button instance can subsequently have event handlers bound to it. Therefore, the instance provides a meaningful button. If you create a button instance in a situation where the only way to bind handlers is subclassing, then that instance is not meaningful, as no event handlers can be bound to it. It's a question of what's possible rather than of what's actually done, essentially. -DavidMcLean] So you are saying you want to be able to do something like Example 8490? (Putting aside whether it's good design or not.) [The ability to add methods to a particular instance after its instantiation does address the complaint, in the sense that the instance is no longer "meaningless", but it implies a strange blend of classical and prototypical OO, and I believe it still doesn't resolve the conceptual problem since hanging additional methods off an instance involves changing its interface on-the-fly. -DavidMcLean] Re: "it implies a strange blend of classical and prototypical OO" -- Yes, it's called making OO more competitive with FP. I don't know what you mean by "changing its interface on the fly". Isn't that what a dangling HOF does? [RubyLanguage has the same strange blend. Why not go for pure prototypes? As for changing the interface, no? Not at all? The interface of an object is the set of operations that can be performed with it; adding an extra method changes that, while adding an event handler does not. -DavidMcLean] We could have "locking" mechanisms in the language, but I'm not sure it would help anything much in a practical sense. Generally we want the ability to customize objects/classes. I didn't like Java's "final" for that reason: let me "locally" customize stuff as I see fit. As far as whether to use pure prototypes, I don't know if they could be flexible enough without goofy syntax. At this point we are just looking at the possibilities rather than putting syntax and OO conventions in stone. * [Pure prototypes can definitely be "flexible enough without goofy syntax" if classical OO can be, since prototypical OO trivially subsumes classical OO (just define an object that you treat as though it were a class, putting all the methods on it and using clones of it as instances). -DavidMcLean] * Cloning (any) large attributes and/or method code kind of seems like a resource waste. But it's mostly a minor side-topic. Either ancestor tree traversal or cloning would probably work for the examples I gave. -t * ''CopyOnWrite means cloning is not necessarily a resource waste. What is "ancestor tree traversal"?'' * That's essentially using a form of tree-traversal under-the-hood. By "ancestor tree traversal" I mean if a given attribute/method is not defined in the current object, then the parent (ancestor) is recursively searched until they define it, or until we reach the top, and the sought-after attribute/method (result) remains undefined. That's "traditional" OOP, more or less. Cloning could make the "also run parent" feature we talked about elsewhere a bit sticky and/or confusing. It just seems to me we have more options if we keep and use a tie to ancestors. We can address ancestor parts/context/etc. when needed. Even if we can't envision such uses now, it keeps the door open. And explicit cloning is not prevented anyhow; we could have separate operators for those. Thus, we can have both worlds as needed, with ancestor traversal being the preferred. -t * ''I see. What I don't see is how your use of overridden methods can handle multiple, independent event handlers fired for a single event. For a given Button, there may be an explicit O''''''nClick handler defined by the developer, but the form the button is used in may want to add its own O''''''nClick handler to the Button. Other widgets in the same form may want to add O''''''nClick handlers to every Button, too. So, any given Button may have the one explicit O''''''nClick handler defined by the developer plus multiple O''''''nClick handlers defined by various components of the environment the Button is used in.'' * That gets into how the "back end" works, and there are multiple angles to take on that. I'll float one approach here: define the on-click event for the form also. The "event" parameter would have "targetObject" as an attribute: class formX extends Form { onClick(event) { // method if (event.targetObject.name=="buttonX") { console.write("The form also responded to buttonX click.") } } } * If we wanted a pre-selected group of buttons to respond, they can add an attribute "belongToGroup7". class formX extends Form { onClick(event) { if (isDefined(event.targetObject.belongToGroup7)) { console.write("A Group 7 button was clicked.") } } buttonX extends Button { belongToGroup7 = True; // define an attribute onClick(event) {whatEver();} } buttonY extends Button { belongToGroup7 = True; onClick(event) {whatEver();} } buttonZ extends Button { // No group membership <----NOTE onClick(event) {whatEver();} } } * ''That appears to require considerable complexity for something that is very common, and otherwise very simple. The ability to trivially add multiple handlers to any component is fundamental to modern GUIs. Your approach appears to make it awkward.'' * This seems pretty simple to me. I don't understand your complaint. What are you comparing it to? * ''I'm not clear what the form's onClick() event is intended to illustrate. When would it be invoked? Are you presuming that every button onClick automatically delegates to its containing form's onClick? If so, that would only allow one event handler per widget and one for the containing form. It still doesn't allow widgets to add an arbitrary number of event handlers to each other, nor does it allow outside code to add arbitrary event handlers to any widget. Anyway, using conventions that allow multiple event handlers per event, your "belongToGroup7" example would simply be:'' buttonX.onClick.add((event) -> whatEver()); buttonY.onClick.add((event) -> whatEver()); buttonZ.onClick.add((event) -> whatEver()); . ** An on-click method at the form level would not usurp the button-level on-click method. I'll have more to say about event architecture later. * ''It appears your example still doesn't permit an arbitrary number of multiple handlers per component event. For example, buttonZ only has one event handler that fires whatEver(). What if buttonY wants to be notified whenever buttonZ is pressed, without interfering with buttonZ's existing onClick handler? Using conventions that allow multiple event handlers per event, buttonY simply invokes buttonZ.onClick.add((event) -> ...something...). Anything should be able to register an arbitrary number of event handlers with any component that generates events.'' ** I still don't know what you mean. How about a UseCase. "buttonY wants to be notified" doesn't mean anything clear enough for me to turn it into a draft technical spec or implementation without wildly guessing at random. ** ''What I mean is that buttonY should be able to register an event handler with buttonX so that whenever buttonX is pushed, some code in buttonY is invoked. For example, buttonX is a 'start' button. When the 'start' button is pushed, buttonY -- the 'stop' button -- should turn itself from grey to red. In general, any component should be able to register an event handler with any other component, without affecting the other event handlers already registered on that component. This is essential for developing modern GUIs.'' ** See NodeJsAndHofGuiDiscussionThree. * Note that another approach for the membership requirement is to subclass a button sub-type, and use the PageAnchor parent_run_01 technique. * ''Why do you deprecate one paradigm -- FunctionalProgramming -- in favour of another, AspectOrientedProgramming?'' * Mixing too many paradigms is too confusing to typical staff in my experience. I know you will probably disagree. Let's not reinvent that battle here unless you truly have something new to say about it. Whether you classify it as AOP, it's still based around and/or an extension of OOP rather than a completely different animal. ''Classes declared as 'final' are rare, generally defined for technical reasons that fundamentally preclude inheritance (e.g., some serialisation mechanisms, built-in "special" types, etc.); 'final' variables are how Java defines constants. Methods declared as 'final' signal the compiler to apply the maximum of performance optimisation, roughly equivalent to C++'s 'inline'.'' I once encountered a case that didn't seem like a technical reason, and others complained about it also online. I don't remember the details, so don't ask. Anyhow, if we had an interface that accepted a map as an input parameter, for example, adding extra key/value pairs to that map is generally not considered a problem; any extra stuff in the map is typically ignored. If you are thinking of "locking" in types etc., protection-oriented syntax or key-words can be added to a language. But I don't see how HOF's prevent such anyhow. If a HOF returns a string for an interface that expects a number, we have the same problem (although it may depend on language). --------- '''Multiple Handler Issue''' Re: "As for the multiple-handler issue, the GUI framework generally needs to do work of its own when you click a button,..." -- Yes, but isn't that done BEFORE it calls "onClick"? The GUI framework typically calls an "onClick" method, not the app developer, which implies that the GUI framework can do whatever it pleases before doing the onClick method(s). [That's one approach, and if the framework is simple enough that's perfectly viable. If there're a lot of aspects that need to react to a click event, though, in a more elaborate framework, then letting them hook in separately is going to be a lot tidier. In addition, presuming that the application developer will have no use for multiple handlers simply because your framework doesn't use them internally isn't sensible framework design. -DavidMcLean] Re: "plus you need to add your own action, at the minimum; under your approach, do you need to explicitly invoke the method in the superclass to make that work?" -- I need clarification on this. There are different ways to design a GUI event system, but here is one way to go about it. The base Button class defines a constructor. When an explicit button is defined (allocated) this constructor runs for the button and establishes or registers a reference of the newly allocated button instance object to the GUI system. (The pointer could be a RAM address or the object name). When that button is clicked, this reference to the object is used to see if any onClick event is defined for that object, and runs it if it exists. [So the base classes would invariably have ''absolutely no'' behaviour in their on* methods, under this design? Otherwise, it becomes necessary to invoke the superclass methods explicitly to guarantee proper handling. -DavidMcLean] I don't see a need for such at this point. [A need for any behaviour existing in the base-class on* methods, you mean? -DavidMcLean] Correct, I currently see ''no'' need for it. Well, except maybe logging a "not-handled" warning message. [Alright. Reasonable, assuming a fairly simple framework, I suppose. -DavidMcLean] PageAnchor parent_run_01 If you can envision a useful scenario, please do. Note that a language can have an "always (run) before" and "always after" keyword set that tells it to run the current (parent) method even if a child overrides it (although it's really sort of prepending or appending instead of "override", technically). [True -- that's a fairly common AspectOrientedProgramming feature, actually. A full complement of AOP features would make on* methods perfectly viable as a solution, by my reckoning, since that would imply different components of the framework could hook into the event methods arbitrarily as necessary with before/after/around advice. Cool. -DavidMcLean] One syntactic approach is a marker or dummy method in the parent to indicate where the child method(s) run such that "before" or "after" is determined by where in the method code one puts the marker. For example, if you put the marker at the end, then the child runs "after" the parent method code. If you put it in the middle, then half runs before and half after. [That seems worse than proper AspectOrientedProgramming facilities, since it leaves the decision of hook position in the definition of the original method; if the parent method failed to provide a hook point at all, then there'd be no options for hooking. With advice, as AOP actually provides, multiple hooks may be inserted and any of them may be before, after, or "around" (the hook itself chooses when and if to run the original code), which is far more flexible. -DavidMcLean] ------ // Example 8562 -- syntactically trimmed class buttonFoo:Button { location = new Point(34, 129); title = "Click Me!"; onClick(event) { console("Clicked button foo at " & event.eventTime); } } [With the typical API and naming conventions of JavaLanguage or CsharpLanguage, the above would typically be implemented along the lines of:] Button buttonFoo = new Button(); buttonFoo.location = new Point(34, 129); buttonFoo.title = "Click Me!"; buttonFoo.onClick.add(event -> console("Clicked button foo at " & event.eventTime)); [This example did already appear on NodeJsAndHofGuiDiscussion, so I'm not sure why we need it again, but nonetheless. -DavidMcLean] As far as code volume, it looks pretty much the '''same''' to me, perhaps even slightly less. And I only have to use one paradigm instead of mix two, reducing the potential for confusion. Incidentally, in my opinion, the last line would be more readable as: buttonFoo.onClick.add( event -> console("Clicked button foo at " & event.eventTime) ); Or perhaps buttonFoo.onClick.add(event -> console("Clicked button foo at " & event.eventTime) ); [You're right regarding volume and regarding code formatting; indeed, realistically I'd probably use your second proposed formatting, as I often do in CoffeeScript. This isn't a demonstration of formatting, though. I'd doubt there's more potential confusion in my approach, considering PublishAndSubscribe is a cornerstone of OO designs. However, consider this: What happens when we want the button to do something ''real''? For instance, say I put my above code inside the form class's initialiser. Here's a sample form class:] class MyForm extends Form { init() { Button buttonFoo = new Button(); buttonFoo.location = new Point(34, 129); buttonFoo.title = "Refresh"; buttonFoo.onClick.add(e -> this.reCalculate()); this.widgets.add(buttonFoo); } reCalculate() { // do some stuff, update the form's output } } [Notice that what the button does depends on the context it's called in -- it invokes a method on the form class, under this setup, which potentially affects every widget in the form as well as the model data lying behind the form. If the button's independent of the form, how do you cleanly assign a handler that operates on the form as a whole? -DavidMcLean] I did indeed forget to describe how to bind it to a panel/form/window. One way to do it is create a middle-man class that binds it: class formXbutton:Button { container = formX; } class buttonFoo:formXbutton {...} Or explicitly set it in each button: class buttonFoo:Button { container = formX; location = new Point(34, 129); title = "Click Me!"; onClick(event) { formX.reCalculate(); // call a method of the form } } PageAnchor NestedClasses01 [Where does formX come from in these examples? How does the namespacing work? Are these classes nested inside the form class? If so, why write formX instead of "this" or some sort of "parent" keyword? -DavidMcLean] Since objects and classes are the same thing here, we'd probably want to allow classes to be nested, and in that sense you are correct, we could do that also. It wouldn't necessarily be a "parent" class, but an outer container class since it's not the same kind of "thing". This may allow a way to have '''automatic default''' form scope so that we don't have to explicitly set it. The gut implementation, such as the top master button class, could check the existence of such: // Example 8653 // Master button class setting default container as a short-cut (yet still overridable) if (isObject(outer)) {container=outer;} Here "outer" is somewhat similar to "self" in that it references the "outer" class/object. I realize scoping rules can result in sticky tradeoffs and WaterbedTheory. [So do you ''need'' to nest classes to get a reference to the container? It's still unclear where "formX" comes from in your above sample; is it a global? Is baking references to containers into the actual widget classes a good idea? For example, what happens if you want to reuse the same widget across a few forms, when the widget carries a reference to its container? (With an .addEventListener() approach, the container reference is captured in the listener itself because of closures.) -DavidMcLean] "FormX" is the containing class/object. This nesting is not really different than Java, except the fact that objects and classes are the same thing here. * [You've missed the intent of my question again, sorry. I know what formX ''is'' -- a reference to the form object or class that will contain the widget. I don't know where it ''comes from''. Is it a global variable? Regional/module-level? A magic keyword that gets you the containing form (unlikely, considering it has X in it, but still possible considering this is an imaginary language)? How's it work? -DavidMcLean] * See Example outer64 below. We don't have to nest classes if one explicitly sets the context, such as with "container = formX;" above. However, if the nesting is set up as expected, then we wouldn't need to set the reference for each button, for it could automatically "inherent" it per Example 8653. We thus have a choice of doing it both ways: 1) lone, or 2) nested, with the lone one requiring more code. But this class nesting is not to be confused with OOP inheritance: it's a "coded" default in this "form" case, not an OO-inherited one. I agree that nested class/object relationships versus OOP relationships is confusing, and this is why TOP should be involved: code is shitty for managing/tracking myriad multi-factored relationships. Relational is just a better tool for that, even if we have to use code generation as a final step because the DB brand cannot handle direct code snippets. * [How exactly would one confuse inheritance with nested classes? Those are generally pretty clearly delineated; inheritance produces potentially-altered subclasses that should be substitutable for instances of the base class, while nested classes produce entirely distinct classes that merely reference their containing class through lexical scope. Of course, the functionality of either or both of these features varies among languages (CeePlusPlus doesn't capture the containing class's instance in instances of inner classes, for example), but they seem quite distinct from here. -DavidMcLean] * It can confuse some newbies. Just wanted to make that clear anyhow. * [Fair enough.] As far as the code-centric examples, generally the class nesting follows GUI object relationships by convention, and OOP inheritance is used more for code-related issues. ------------------------ Example outer64 // --- GUI library class Form extends Gui''''''Widget { // master form class } class Button extends Gui''''''Widget { // master button class container = null; // establish an attribute of this class method constructor() { // line "sally" if (isObject(outer)) { container=outer; } } } // --- Specific Application Code class appX extends Gui''''''App { class formX extends Form { // instance of form class buttonX extends Button { // instance of button, line "brenda" method onClick(event) { console.write("Button is in form instance: " + container.name); // shows "formX" } } } } // syntax chosen for clarity, not brevity An instance's class-nest scope determines its context even if it runs a parent method via inheritance. When the "buttonX" object/class is instantiated (line "brenda"), the Button class runs its constructor (line "sally"), and it runs in the current object's scope such that "outer" returns a reference to the formX object. (Remember, "outer" is a scope word comparable to "self". A language could have a lot of scope words for various purposes, but we won't get into that here.) [So "outer" is bound lexically to each class, and when you access it from a method it dispatches based on the object's actual class rather than where the method's defined? That seems a little confusing as a scoping method -- it doesn't cleanly correspond to either lexical or dynamic scoping -- but seems generally viable and wouldn't take much more getting-used-to than any other scope approach. What about the case where you want the same widget (same colour, title, position, whatever) displayed on two forms, with different behaviour? How does that come out in this design? -DavidMcLean] One approach is to subclass a button containing the common items, and overriding any difference. Another is to use an IF statement on "container.name". And a third approach is to call a form-level method for the differing methods ("container.mySpecialFormMethod(event)"). A fourth approach may be to create a template form class, and then override the differences, but I haven't really thought out all the implications of such. [The option of an if statement on "container.name", presumably in the button class's onClick(), is unconscionably mixing concerns. The rest of those seem reasonable, given sufficiently "nice" syntax for working with the object system. I'm not sure there's necessarily any ''gain'' over the typical approach to GUI widgets, but it's at least looking comparable rather than horrifically worse. Nice. -DavidMcLean] Having a direct and simple on-click event attached to the button object/class to me seems the most natural and strait-forward and uses a paradigm already in use for an application: OO. We thus cut down on paradigms and make the code strait-forward. And I don't see it as inherently "more code"; it's roughly a wash. I realize "strait-forward" is perhaps subjective or subject to an AnecdoteImpasse on what typical developers prefer, but if we are at an impasse then we are at an impasse, and at this point LetTheReaderDecide and call it day. -t [I see no value in cutting down on paradigms, but if that's your goal this does seem to be a way to do it. -DavidMcLean] ''This "cutting down on paradigms" seems like programming philosophy driving programming practicality. Top, if we told you that Java was dropping lambdas, replacing them with a shortcut syntax for defining anonymous inner classes, would it make a difference? For example, this is the usual way of adding a Java event handler to a button:'' Button buttonFoo = new Button(); buttonFoo.location = new Point(34, 129); buttonFoo.title = "Click Me!"; buttonFoo.addActionListener(new ActionListener() { void actionPerformed(ActionEvent event) console("Clicked button foo at " & event.eventTime); } }); ''What if we got rid of lambdas, and instead had a shortcut syntax for defining an ActionListener that looked like this?'' Button buttonFoo = new Button(); buttonFoo.location = new Point(34, 129); buttonFoo.title = "Click Me!"; buttonFoo.addActionListener((event) -> console("Clicked button foo at " & event.eventTime)); ''Would that be better? Remember, it's not a FunctionalProgramming lambda -- we got rid of those -- it's a shortcut syntax for defining anonymous inner classes.'' Example 8562 to me seems the most natural because it uses regular plain-jane OOP. No funny arrows, no curly braces inside parenthesis, etc. I know you will probably disagree regarding staffing/training/hiring/confusion, but let's not reinvent that battle here unless you have something truly new to add to it. It won't be settled via words nor repetition. OOP can be pretty flexible for "block management" if tuned right such that we don't need to introduce FP and HOF-like techniques and syntax. Master the OOP for such and '''dispense with paradigm clutter''' of competing block-management techniques/syntax. ''What does "master the OOP for such" mean in Java?'' ''What is "paradigm clutter"? That sounds like something you made up.'' It wasn't intended as a formal term. We should have a consistent way to specify "passable" blocks (for lack of a better term), and plain-jane OOP methods appear to be good enough in a well-designed OOP language (which Java doesn't qualify for in my book). On occasion it may be somewhat more code to live with a limited "kind" of passable blocks rather than also use HOF's, etc, but worth it in terms of consistency and familiarity. ''So code blocks are fine if they're assigned to named constants (that's what a "plain-jane OOP method" is) but not if they can be passed as parameters or assigned to variables?'' Generally yes, because the syntax and context is confusing and different for anonymous ones. And it gives a reference name for debuggers and human discussors to work with, and allows a place to hang related attributes and other methods off of if features expand in the future. Such regimenetation improves fungible team communication: all cars must have a license plate. If that bothers libertarian coders, screw-em, they can move to Somalia. * [Is it fine to have both anonymous and named code blocks if they're given exactly the same syntax, as in CoffeeScript? Does that solve the "confusing and different" issue? -DavidMcLean] * Are you trying to trick me into learning CoffeeScript? Tsk tsk tsk. Aren't "named blocks" called "functions"? * [I'm using CoffeeScript as an example because it has the same syntax for both anonymous and named functions, which, yes, are the same thing as code blocks. Does it help with your issue there? Does the unified syntax avoid the "confusing and different" problem? -DavidMcLean] * Its syntax is so different from "typical" in general that there are probably other issues that overshadow that question alone. * [How so? Are you confusing it with IoLanguage, PrologLanguage, AplLanguage, ForthLanguage, or SmalltalkLanguage, perhaps? CoffeeScript's syntax is hardly unorthodox, being merely a blend of Ruby's and Python's with few wholly original additions. In any case, it's irrelevant what the other syntax is like. Considered by itself, does unifying the syntax for named and anonymous functions remove your issue with the two being "confusing and different"? For another example, imagine I took JavaScript and deleted the function declaration syntax, changing no other syntactic features whatsoever. Now, instead of "function f(x) {}", you need to write "var f = function(x) {};". It's more verbose, to be sure, which isn't surprising given that JS is a generally verbose language, but, under such a language, are anonymous and named functions still "confusing and different"? Is "var f = function(x) {};" really fundamentally distinct and hence confusing compared to, say, "g(function(x) {});"? Or are they both similar uses of functions, both trivially falling out of the first-class nature of functions in JS? -DavidMcLean] * I do not wish to comment further on CoffeeScript at this time. * [Then don't. Respond to my actual question, and ignore the mentions of CoffeeScript, if you like; the question still stands independent of examples. Again, it was this: Does unifying the syntax for named and for anonymous functions, such that both are written exactly the same way, eliminate your "confusing and different" issue that applies when they're provided with distinct syntax? You can use the JS hypothetical if you do need an example to work with. -DavidMcLean] * Can you present pseudo-code examples that don't deviate significantly from "conventional" AlgolFamily/C-style/VB/Pascal/Fortran syntax and conventions, at least for the "classic" language idioms? I don't want to "goof up" the commonly-used stuff for the sake of the rest. * [That's why I chose JS as an example, it being the only "scripty" language I'm aware of that has conventional AlgolFamily/C-style syntax. Ruby, Python, and Perl all obviously deviate even further. Again, however, it doesn't matter what any other part of the language is like; given any language you like to start with, if you replace the syntaxes for named and anonymous functions with a single syntax (such as JavaScript's "function() {}", which necessitates the use of "var f = function() {}" for a named function), does this eliminate the "confusing and different" distinctions in syntax and context between anonymous and named functions? Ignore all other syntax and language behaviour, and just answer the actual question. -DavidMcLean] * I choose not to answer at this time. Maybe when other sub-topics settle, I'll revisit this. * ''Why do you choose not to answer? It seems to be a simple and reasonable question.'' * "How is typical staff going to react to syntax X" is not an easy question to answer well. * ''But that's not what you were asked. You were asked if you thought that using the same syntax for anonymous and named functions would address your concern that they otherwise have "confusing and different" syntax.'' ''Somalia? Huh? That appears to be an emotional reaction rather than a rational one. Your distinction between blocks assigned to a constant and blocks assigned to a variable appears to be arbitrary, as debuggers treat them equivalently. "Human discussors" are no more an issue with blocks assigned to a variable than any other block, like FOR loops and WHILE loops which don't have a "reference name" either.'' Sorry, I misread the "constant" thing. I'll try to re-word it better. And loops are generally used for different purposes such that you are comparing apples to oranges. ''In typical imperative programming languages, a FOR or WHILE loop is a flow-control construct that can repeatedly execute the anonymous block that is statically assigned to it. An anonymous block is an anonymous block whether it's:'' * ''Statically assigned to a loop, as per FOR/WHILE loops in typical imperative programming languages, e.g., "while (p == 2) '''{writeln("zot");}'''";'' * ''Statically assigned to a named constant, which makes it a "conventional" named function, procedure or method, e.g., "function blah() '''{writeln("zot");}'''";'' * ''Dynamically assigned to a variable -- such a block is often called a "lambda expression" or anonymous function, e.g., "var blah = function() '''{writeln("zot");}'''"; or'' * ''Dynamically passed to or returned from a function, which makes it a HigherOrderFunction, e.g., "blat(function() '''{writeln("zot");}''')". In some FunctionalProgramming languages, FOR/WHILE loops are implemented as HigherOrderFunction''''''s.'' ''It's not "comparing applies to oranges", because it's all oranges. From the debugger's point of view, all blocks are anonymous and handled the same way.'' But we don't pass references to loops or IF blocks around. OOP and HOF's are a way to '''pass around references to "behavior"''', as are functions. Loops and conditionals are intended to be used only in their current environment. ''Sure. When anonymous blocks are dynamic (see above re "dynamically assigned" and "dynamically passed") they can be passed around, just like objects and other values. So?'' Thus, they are not comparable to regular loop and condition blocks. ''Of course they are. They're blocks of code. Why would they be any different? It's no different from an instance of a class, which is precisely the same instance whether it's passed around or not.'' They are different. If we intend to pass them around and/or reference them from a wider variety of code spots, then we typically need extra info and maintenance-friendly conventions to work with them effectively. A box of stuff sitting in your closet doesn't need the same labels and packaging as a box you intend to ship to Timbuktu. Or even a "sub-box" inside the Timbuktu-destined box. [While your metaphor is true, it isn't particularly applicable to blocks of code. Lambda expressions are in most cases referenced ''exactly once'', as in cases like f(x -> x*2) where the anonymous function is immediately passed to another function, so there's no demand for "extra info" in those situations. When a particular function is to be referenced from multiple places, it's given a name -- it has to be, since rewriting the expression each time it's used will produce a different function -- and then there is no meaningful distinction between that function defined by a lambda and a function defined with "normal" declaration syntax (excepting degenerate cases like PHP's horrendous interpretation of functions and "closures" as fundamentally distinct). Static functions, from the language's perspective, have only their name and their type (the latter of which might not even be explicitly accessible, if working in a dynamically-typed language), and we don't need "extra info" to work with such functions effectively; why would we need more info if the function's assigned to a variable dynamically rather than statically? -DavidMcLean] Whether they are mentally comparable to loops and conditionals or not is turning into a rather obtuse discussion. My main point is that with decent OO and OO libraries, we don't need HOF's and lambda's for GUI programming. If OO can do the job, then don't introduce or depend on yet another language idiom to do the same thing. (H/L may shave code size SLIGHTLY in some cases, but that's not worth the added confusion by my judgement. Consistency often overrides code size in terms of team grokkability.) I am comparing them to OOP, NOT loops etc. ''Your alleged confusion over "yet another language idiom" (e.g., lambda expressions) appears to be baseless, especially as certain language constructs like lambda expressions appear to simplify real UseCase''''''s, like being able to attach an arbitrary number of independent event handlers to an event without the labyrinthine circumlocution described in NodeJsAndHofGuiDiscussionThree. In short, I see trivial evidence that "yet another language idiom" (e.g., lambda expressions) can simplify code (and thus make it less confusing) but no evidence that "yet another language idiom" causes confusion. Can you provide evidence that it causes confusion?'' See NodeJsAndHofGuiDiscussionThree regarding event handling. As far as "evidence", see LetReaderDecideEvidenceAgreement. ''The claim that HOFs and lambda expressions cause confusion is yours alone. If you want "agreement", retract your claim until you have evidence to back it up.'' Moved replies to EvidenceDiscussion