Helvetical Fronting


  • BINNED

    @boomzilla said:

    It's also more obvious (to me) that it's not something that happens now, but something that gets called later.

    You don't nest anonymous functions 4 levels deep because it all happens "now". On the contrary, the whole mess is a consequence of having to call functions when an async operation finishes, which you have to do a lot in a modern web app.

    You could register event handlers, yes, but it's one of the rare occasions when nesting is actually more readable because you can just read it all sequentially instead of jumping around the file.

    Also, note that in most situations where you use nested callbacks you don't actually call anything after the end of the function. It usually just looks like this in the end:

                });
            });
        });
    });
    

  • ♿ (Parody)

    @Onyx said:

    Also, note that in most situations where you use nested callbacks you don't actually call anything after the end of the function. It usually just looks like this in the end:

    At which point you could just put the functions right below there and still read it sequentially, right? You can do that in js, can't you? (Some console testing says YES.)



  • Modern JS is all about taking a very simple language and making it REALLY FUCKING COMPLICATED, also pretending it works well as a functional language.


  • BINNED

    @boomzilla said:

    At which point you could just put the functions right below there and still read it sequentially, right?

    Yes, but we're talking async operations here. And you want to make them async so your browser doesn't block while waiting for that image to load. The way to solve that are callbacks.

    You can either write callbacks as anonymous functions, or create a separate one for each callback. Now, that's all fine and dandy when it all still simple, non-branching, and the next bit of data is not dependent on the data you just loaded. But it often is. And following function calls in that kind of setup is a huge PITA.

    DISCLAIMER: I'm talking about JavaSciript in web apps. If you just use it as a general-purpose scripting language almost all of my points above become moot. In that case, yes, anonymous functions just muddy the waters and should be avoided.



  • @ijij said:

    Which function set which property in the someData object?

    Our entire codebase is this antipattern...

    Don't know if this is good or bad mental health....

    I forgot, we don't have luxury of one someData object, someData is actually a list of objects... an ever-so-subtly changing* list as you descend the levels... :facepalm: :facepalm:


    *some of the objects change names, some change types and nearly the same names...


  • ♿ (Parody)

    @Onyx said:

    You can either write callbacks as anonymous functions, or create a separate one for each callback. Now, that's all fine and dandy when it all still simple, non-branching, and the next bit of data is not dependent on the data you just loaded. But it often is. And following function calls in that kind of setup is a huge PITA.

    I'm not following what you're saying here. Are you building a function's source dynamically? Is it dependent on some bit of data in a scope other than its own?

    I can live with passing something trivial like...

    function awesome(){
        ...stuff...
        var alsoFoo, andBar
        ...stuff...
        $.ajax( { ....
        success: function(){ theRealFunction( data, alsoFoo, andBar ); } });
    }
    
    function theReadFunction( data, myFoo, myBar ){
        ....
    }
    
    

    Or if it really is just a similarly trivial one liner.


  • BINNED

    The example you presented gets a bit of data and passes it into a single function that, presumably, does what it needs to do and exits. In this case I agree that anonymous function just adds confusion.

    But as soon as you go and try do something more complicated having something to the tune of 3 async requests which depend on the result of the previous ones are not uncommon. For example: you ask the server where to redirect the user, which tells you what template you need to load, which might need additional data to render properly.

    There's also stuff like $.each() in jQuery to loop through elements, and it does so in a callback function. And those are usually unique for that specific chunk of data you're loading.

    Obviously, there's a lot of stuff you can abstract out because it's generic enough, but there are equally the same amount of cases where putting those 2 lines that would be in an anonymous callback in a separate function just doesn't make sense because all you gain is some mythical "purity" of the code.

    All I really want is just to make those two input fields red because the username is already taken, and the captcha is wrong. And I'd rather just stick that into an anonymous callback than go pecking and hunting all over the source file to find where the hell is markWrongFieldsInRegistrationForm().


  • FoxDev

    @Onyx said:

    pecking and hunting all over the source file

    find usages?

    or failing that grep?


  • BINNED

    @abarker said:

    No.

    It's a missed opportunity


  • BINNED

    @accalia said:

    find usages?

    Yeah, that one usage of that one function out of approximately gajillion you wrote.

    It's not a matter of finding a function itself, it's following the flow of your logic when it's all scattered into 54 functions, more than half of which are called only and exactly once.

    I'm lucky that my current project is free from that shit, all the forms are generic enough that I can avoid 90% of all the callback nesting shit, but sometimes an anonymous function is just the more readable way. Actually, here, remember this bit of ugly I posted the other day?

    $(function () {
        $('[data-toggle="popover"]').on('click', function(evt) {
           evt.preventDefault();
           $('[data-toggle="popover"]').not(this).popover('destroy');
           $(this).popover({html: true, container: '#main-table'}).popover('show');
           
           $('.popover .close').on('click', function(evt) {
               evt.preventDefault();
               $('[aria-describedby="'+ $(this).closest('.popover').attr('id') + '"]').popover('destroy');
            });
        });
    });
    

    That could be two functions, one of which would be a three-liner and would require another three-liner as a callback.

    Now imagine you have to do something like this for 5 different element types. Over, let's say, 5 pages where they behave differently. Would you rather have 25 such functions with one anonymous callback within them, or 50 functions where 25 of them have a callback function as a parameter? And for what? To replace 4 of those lines with handlePopoverCloseOnPageX()?


  • FoxDev

    @Onyx said:

    all the forms are generic enough that I can avoid 90% of all the callback nesting shit,

    SockSite has forms?


  • BINNED

    @accalia said:

    SockSite has forms?

    I do have a job as well, you know? :P


  • BINNED

    @Onyx said:

    I do have a job

    Working on SockSite?


  • FoxDev

    @Onyx said:

    I do have a job as well, you know? :P

    Wait, you're not just one of Cali's slaves?

    <hugs for cali>

  • FoxDev

    @Onyx said:

    I do have a job as well, you know? :P

    What's a job?


  • BINNED

    @Luhmann said:

    Working on SockSite?

    I wish. It's way more fun than my "proper" one.

    Well, ok, that one can be fun, too, but not lately.


  • BINNED

    @RaceProUK said:

    one of Cali's slaves

    You don't know the slaves around you?


  • Java Dev

    A lot of javascript, and even more so the frameworks, are written to require anonymous callbacks. If only because there's no other way to get extra data in.



  • @PleegWat said:

    A lot of javascript, and even more so the frameworks, are written to require anonymous callbacks. If only because there's no other way to get extra data in.

    Basically -- the problem is that JS callbacks rely on the ability of a nested (whether named or anonymous) function to close over variables in the enclosing scope. You simply can't do that with an out-of-line function definition, as @boomzilla conveniently mostly ignores; you can give it a name or not as you please, but the definition and the use have to share the same scope in order for lexical closures to work. Either that, or you wind up with one-line lambdas that simply close over variables only to forward them to out-of-line functions.



  • @PleegWat said:

    A lot of javascript, and even more so the frameworks, are written to require anonymous callbacks. If only because there's no other way to get extra data in.

    Anonymous callbacks are basically the only feature of JavaScript which isn't broken and terrible, so they get used in all manner of situations where better languages have dedicated keywords to express the concepts (like namespace, or delegate...)



  • You could just write normal procedural code.

    Bonus: the debugger would work.



  • You're aware Brendan Eich was trying to sneak Scheme into Navigator?

    Go functional, or go home, baby.



  • @tar said:

    Scheme […] Go functional, or go home, baby.

    Scheme is not really any more functional than JavaScript. It has lambdas and closures, but so does JavaScript and JavaScript has assignment and so does Scheme. So the only advantage of Scheme concerning functional programming is tail call elimination.

    Scheme would have one advantage though—the infamous call-with-current-continuation would allow writing the omnipresent asynchronous callbacks in a readable fashion (after being hidden behind suitable helper).



  • Tail call optimization isn't exactly a purely functional concept; it's more that only functional language designers actually bother to implement it.

    Now, are you going to post an interesting IDE config, or tell me how Javascript is awesome at macros?



  • @Bulb said:

    Scheme would have one advantage though—the infamous call-with-current-continuation would allow writing the omnipresent asynchronous callbacks in a readable fashion (after being hidden behind suitable helper).

    That's an interesting point, actually. I wonder if it's possible to write a call/cc emulation in pure JS? Maybe a JS-to-JS compiler which rewrites your code into CPS... (Stick that on my list of "stupid things to try if I run out of other stupid things to try"...)


  • ♿ (Parody)

    @tarunik said:

    as @boomzilla conveniently mostly ignores

    Not at all. As I pointed out:

    @tarunik said:

    ...one-line lambdas that simply close over variables only to forward them to out-of-line functions.

    And as I said, that assumes there's something going on there. I'm not absolutist about it, but I'd prefer names to no names where possible.



  • @tar said:

    I wonder if it's possible to write a call/cc emulation in pure JS?

    I am not sure whether full power of call/cc, but you don't need to implement the return-multiple-times bit for async function.

    The rest seems to be doable. You will need to add a keyword to both definitions and calls to asynchronous functions, otherwise you may not reliably know what to transform since JS is dynamic. This will make it more intrusive than call/cc, but it is probably better that way anyway since you often need to be aware there are asynchronous operations underneath something.

    I've seen such asynchronous functions in Vala. They add async to function signature and yield to the calls. They do it over C which does not even have closures, so the implementation is somewhat different (uses the weird feature of C's switch to allow jumping in the middle of loops and conditions), but it shows it is doable (except the multiple returns bit, but I don't think that is much use anyway).



  • This font family, from the guy that made calibri and consolas.



  • @tar said:

    Go functional, or go home, baby.

    You'd better start shaping up your JS fü for the füture.

    http://wiki.ecmascript.org/doku.php?id=strawman:maximally_minimal_classes

    class SkinnedMesh extends THREE.Mesh {
      constructor(geometry, materials) {
        super(geometry, materials);
     
        this.identityMatrix = new THREE.Matrix4();
        this.bones = [];
        this.boneMatrices = [];
        ...
      }
     
      update(camera) {
        ...
        super.update();
      }
    }
    

  • BINNED

    @Eldelshell said:

    ```
    super.update();

    
    I agree with that line.

  • ♿ (Parody)

    @boomzilla said:

    I liked the look of that Solarize theme so I'm trying it out in Eclipse now.

    Nope. The way it's done, selection is messed up. I was also trying it out in Kate and I've shitcanned it there, too. Trying "Robotticket" on Eclipse now. It's the next best first impression among light themes that came with the color theme addon. A nice gray background, which I've always liked.



  • I think I'm starting to hate the CodeReview StackExchange. I like to hang out there and occasionally review things, but it's gotten really dogmatic.

    For instance:

    for(int i = 0; i < 10; i++)
        for(int j = 0; j < 20; j++)
        {
            // Code
        }
    

    ^is bad code. It's inconsistent. But the reason they'd reject it on CR is simply that it does not always use curly braces. That ideology is, however, unrelated to the wrongness.

    You then get stuff like:

    for(int j = 0; j < 20; j++)
    {
        // Code
    
        if(condition)
            DoThing();
        else
            DoSomethingElse();
    }
    

    And they scream about the braces again! Yes, I could assume that the next developer is unfamiliar with C# and will think that whitespace magically means something that it has never meant before in the language, and always use curly braces. I don't. This is a really basic language feature.

    But far worse than that is this:

    //Do your properties like this!
    private string _Thing;
    public string Thing { get { return _Thing; } }
    
    //Or this!
    private string _thing;
    public string Thing { get { return _thing; } }
    

    Sorry, but if your class is so large that you need underscore prefixes on every member to know it's a member, it's too long! And it isn't as if it's hard to make your fields colored differently from locals. Sure, you've managed to get hungarian down to a single character - well done? It doesn't even have the advantage of systems-hungarian, where you might have:

    private string userName;
    private string userId;
    private string clientName;
    private string clientId;
    

    And that's because we have classes now! We don't need to do that anymore! So all we've got is this idiotic variant of hungarian notation that encourages either bad tooling or bad design. And this is suggested to every new user as the best, mostly accepted way. And they only say mostly because I complain every time they make absolute statements about it.

    [/rant]


  • FoxDev

    @Magus said:

    But far worse than that is this:

    //Do your properties like this!
    private string _Thing;
    public string Thing { get { return _Thing; } }
    
    //Or this!
    private string _thing;
    public string Thing { get { return _thing; } }
    ```</blockquote>
    :mask: 
    
    C#, right? Then:
    ```csharp
    //Do your properties like this!
    public string Thing { get; private set; }
    

    SERIOUSLY DISCHORSE‽ SERIOUSLY‽‽‽
    I ain't fucking fixing that…



  • Well, yes, but I'm assuming they're doing something more complicated. I'd do a private set as well if it really was that simple.



  • I like the underscore syntax. It makes it clear which members are private and should be accessed gently. I also like to write constants in ALL_CAPS. And function names in TitleCase and local variables in camelCase.

    That's no dogma. That's just a useful convention, helping you tell different language features apart. Having tings like conventions also helps code written by different programmers able to "mesh" together. It's nice that you have IDE features to help you out with that, but that's just a bonus.

    BTW that's not Hungarian notation either. Depending on which definition you pick, Hungarian is either prefixing variables with type names (eg. iNum, strName) or just a semantic category (eg usrName, rwHeight). These language conventions are neither.


  • :belt_onion:

    @cartman82 said:

    like to write constants in ALL_CAPS. And function names in TitleCase and local variables in camelCase.

    +1

    @cartman82 said:

    prefixing variables with type names (eg. iNum, strName)

    ACK! Killit! Killit now!



  • The thing is though, anything camelCase should already be private. The only additional information the underscore carries is 'this is not local' and the best reason I've ever heard as to why people do it is to avoid this. - which, again, is a basic language feature which you only need if you reuse names.

    The camelCase and PascalCase guidelines are more common - they're part of stylecop if I remember correctly. The main reason the underscore has flourished is that it's the default in Resharper, but I tend to prefer the Microsoft guidelines, which say nothing about prefixes. As for constants, those are also a different color for me, and are generally always PascalCase - but I so rarely use them that it doesn't matter much to me. All caps with underscores is fine if that's the project's convention, but it's another holdover from old languages with worse tooling.

    As for hungarian, yes, I wrote out the full words of the semantic sets rather than abbreviating them, because that is just too disgusting to perpetrate even as an example. But neither has much meaning in C#, which has types and classes. I tend to look at hungarian notation as 'prefixes you use to understand what things are for' - which there is never a good reason for.


  • ♿ (Parody)

    Sorry, but I can't take anything you say seriously because you don't consistently use braces.


  • Java Dev

    I can see the underscore for name collision reasons, assuming there's a good reason to have a separate private member and public property, and the two can't share a name.

    What's the alternatives? realThing? memberThing?



  • @Eldelshell said:

    You'd better start shaping up your JS fü for the füture.

    ...for ES6 functional improvements:

    C:\Users>iojs --harmony_arrow_functions
    > x = (y) => y(x)
    [Function]
    > x(q=>console.log(q.toString()))
    (y) => y(x)
    undefined
    

    Nice use of _ in the option name, there...



  • The usual alternative is to differ by case, which is the only time you'd ever do that. The language is case-sensitive, so this works. I'd far prefer someone who wants that additional information to use some meaningful word as a prefix, but everyone seems to love the underscore. Worse, I've seen someone suggest that all private member variables should have an underscore prefix.

    About the only time I approve of an underscore outside an all caps constant name is when you aren't using the variable of a lambda, like you'd do in some functional languages someThing.Click += (s, _) => someOtherThing.Update(s.Status);



  • Because I insisted on the fact that the word 'standard' is wrong in an answer when talking about always using braces in C#, because Microsoft certainly doesn't suggest it, my comments on an answer were deleted. SE mods are dumb. You don't call something that isn't a standard a standard.



  • Eclipse has a pretty cool feature where you can select exactly which whitespace you want to show. Right now I've got it set to a mode I call ‘simulated ocd’, where it highlights all of the whitespace sins a friend of mine used to complain about: leading spaces (we're mostly using tabs, so this keeps it consistent), enclosed tabs, and trailing whitespace of any kind (except line breaks). Basically, I don't see any whitespace unless it's spurious.



  • Yeah, i use show whitespace at work, partly because we use a language that treats spaces as part of an argument but ignores tabs.



  • I like braces so much, I use double braces:

    int funcer ()
    {{
      for (int i = 0; i < 4; i++)
      {{
        if (i > 4)
        {{
           GetLocalLogger ()->Log ("An error has occured");
        }}
      }}
    }}
    

    I tried to yell at some greenhorns over at CodeReview to do this as well, but it was not well received for some reason.
    I'm currently campaigning them over at meta codereview to reconsider.
    It's a hard fight, but I think they're starting to see the positives and reconsider.


    What I'm trying to get across here is that all developers that care about code style enough to fight with other developers about it are (insert hate here).



  • My complaints about calling something nonstandard standard were listened to, once they were within the chat. I don't care how other people use braces, I only care that they say that there is only one true way. I don't think I will ever recover, however, from the knowledge that what you just posted is totally valid code.



  • @CreatedToDislikeThis said:

    I like braces so much, I use double braces:

        int funcer () {
          {
            for (int i = 0; i &lt; 4; i++) {
              {
                if (i &gt; 4) {
                  {
                     GetLocalLogger ()-&gt;Log ("An error has occured");
                  }
                }
              }
            }
          }
        }
    

    Now everyone's happy.


  • FoxDev



  • A website with a texture background... I cannot trust it. I mean, that's up there with centered, linear gradients!

    Also, whitesmiths and gnu styles are absolutely horrible.


  • FoxDev

    it's also sprinkled rather liberally with these glyphs (for me at least)

    still it's a fun read for glimpses into computing history.

    i usually use a hybrid of K&K and Allmans styles


Log in to reply