Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Unexpected parameter.boolean behavior

in Bugs Posts: 1,277

Project has nothing in it except:


parameter.boolean("doNotPrint", false, function() print("oops") end)

Outputs “oops” twice upon startup, as shown in attached image.

Tagged:

Comments

  • dave1707dave1707 Mod
    Posts: 9,415

    @UberGoober I think that’s just the way Codea works if you put something outside any function. If you just have a single print statement, it will print twice. There’s very few things I’ll put outside of a Codea function.

  • Posts: 1,277

    @dave1707 unexpected behavior is unexpected behavior. If “that’s just the way Codea works” there should be documentation of it.

  • Posts: 1,277

    Also


    function enclosed() parameter.boolean("doNotPrint", false, function() print("oops") end) end enclosed()

    ...same result

  • dave1707dave1707 Mod
    Posts: 9,415

    @UberGoober I’m sure there’s a lot of things that Codea does that isn’t documented. Apparently Codea makes two passes thru the code before it executes the functions setup and draw.

  • Posts: 1,277

    @dave1707 there are jillions of things Codea doesn’t document. I’m nonplussed at this. If you’re saying something other than “Codea has lots of bugs, big deal,” it’s not clear to me.

  • Posts: 1,277

    @dave1707 also are you really looking at what’s going on in that code?

    What’s happening is not the result of Codea “going through the code twice” because the code never explicitly calls or changes the parameter.

    The parameter is established, and the callback function of the parameter is called twice, without any of the rest of the code referencing it at all.

  • edited April 22 Posts: 2,348

    @Simeon - probably me not programming the parameter command properly, but - when I set up say parameter.integer(“test”, 1,50,35) and run the code I get an error for undefined integer ‘test’. I have seen this in a few versions of Codea, I get round it by defining test before the parameter setup.

  • dave1707dave1707 Mod
    Posts: 9,415

    It’s possible I asked @Simeon why Codea executes code the way it does probably 7 or 8 years ago when I noticed that. It doesn’t affect how Codea works or the way I code, so I probably just said OK and kept writing code. There’s just a few things that I code outside of any function so it’s taken care of before the regular code starts executing.

  • Posts: 1,089

    i suspect that parameters' functions are called when they are set up. and free code outside functions getting executed as soon as compiled seems unsurprising. that's kind of what one would expect, isn't it?

  • Posts: 1,089

    it might be nice if everything were documented, but it would take more time than anyone has to read it.

    since everything needs to be prioritized, i'd like to see things documented that are hard to figure out, or literally impossible to find, like the stuff inside craft.

    and i'd help with that writing if there's a livable way that i could.

  • dave1707dave1707 Mod
    Posts: 9,415

    @RonJeffries I once requested a tree type flowchart of all the Craft commands just so it would be easy to see how everything in Craft was connected.

  • edited April 22 Posts: 1,089

    yes. obvs there's a lot to it. i would love to help if i could.

  • Posts: 1,277
    @RonJeffries I’m entirely an autodidact, so perhaps I ought to be expecting code to be run when it’s not explicitly called, but I never had the class on “when code runs without you telling it to.”

    That said, working in both Xcode and Visual Studio gives me no reason to expect code to be run when I haven’t called it, so you saying it’s “what one would expect” is itself surprising to me.

    As to things being hard to figure out, figuring out that this happens has taken me hours upon hours to track down, over the course of at least a week, and like I said maybe that’s on me for not having a formal programming education, but I will also point out that AFAIK Codea is not intended exclusively for people who took the class on when code runs without any apparent reason.
  • dave1707dave1707 Mod
    Posts: 9,415

    @UberGoober I’m not sure why you’re surprised by this. Anything that gets keyed in the editor will execute when the run icon is pressed. If it’s inside a function then the code will run when that function is called. If it’s not inside a function, it will get run when the run icon is pressed and before function code. Maybe that’s not intuitive, but I’m not sure when or how you thought code not inside a function would get executed. I don’t use Xcode or Visual Studio, so I don’t know how or when code gets executed. I’m sure any code that’s keyed in will run when executed.

  • edited April 22 Posts: 1,277

    @dave1707 I’m not sure why you aren’t getting this:

    If it’s inside a function then the code will run when that function is called.

    The function is never called. The containing function is called in the second example, but the parameter one isn’t. The parameter function is supposed to be called when the parameter is changed. The parameter is never changed in any of my examples.

    Also neither of your dismissals explains why the function is called twice.

    Expecting code that isn’t called to execute anyway is odd to me, but expecting it to execute twice is even odder.

  • dave1707dave1707 Mod
    Posts: 9,415

    @UberGoober Here’s the last thing you showed above. You’re calling the function enclosed(). In the post above that, the parameter is getting called because it’s not in a function.

    function enclosed()        
        parameter.boolean("doNotPrint", false, function()
            print("oops")
        end)
    end
    
    enclosed()      <<<——  You’re calling the function right here.
    
  • edited April 23 Posts: 1,277
    Okay but
  • edited April 23 Posts: 1,089

    ok, this is more odd than i thought. it prints hello twice. here's the program

    print("hello")
    

    once i can get. but twice? why?

    @dave1707 note twice. weird.

  • Posts: 1,277

    So @dave1707, I’ve done dumb things in my life, and Lord knows I could be doing something wrong, right here, too, but dangit I know when I’ve written a function call.

    I think you guys think I’m saying something completely without merit, and so you’re making analyses of the situation that have no grasp of it.

    The callback function defined by the parameter is never explicitly called.

    Calling a function in which a parameter control is defined is not explicitly calling the callback function of that parameter.

    A parameter definition made outside a function (at root level) is not explicitly calling any callback function defined by that parameter.

    In both cases a parameter is being initialized, it’s not being called.

    The function at the end of parameter definitions is explicitly named a callback, in other words it does something in response to being set. I am not setting the parameter anywhere, so the callback should not be called.

    Let’s say you have a parameter that defines a button. When should the action associated with the button be called?

    When and only when the button is pressed, right?

    Should the action be automatically called at the place in the code where you define the button? Of course not.

    The expected behavior of any control is that it only activates in response to user interaction.

    This control is activating not only without any user interaction, it’s activating without explicit instructions in the code to do so.

  • edited April 23 Posts: 171

    no doubt you are initializing this parameter inside the setup function yes?

    i noticed the setup function gets called by codea twice (a good reason to avoid using setup)

    parameters with callbacks get triggered during initiation also (my guess is this to keep the expectation that the callback will run with the initial value as well as when you change the value)

    so you're seeing "oops" twice because the callback is triggered by the initial value and setup runs twice

    these are some of the reasons why i do not like parameters and setup, my goal is to eventually never use parameters. i only use setup to call a wrapper class i name App whose init kicks off the initial loading screen, after that i push all my subsequent loading and custom parameters into the draw function (by partitioning draw with internal loops and that Thread class from the other topic)

    i believe this approach is called Inversion of Control. and it just makes sense that you want to be able to control what is visible to the player (like company logos, main menu screen) without having to wait for setup to run, and to have your own debug menu/options/cheats that are not bound to the limits of parameters

    edit

    setup is not called twice-

  • dave1707dave1707 Mod
    edited April 23 Posts: 9,415

    @UberGoober @RonJeffries At the start of this discussion I stated that it will print twice. Why I don’t know, but it does and has always done so for a long as I remember. As for a parameter callback function, it always gets executed once when the program starts. In my projects that have parameter callbacks, I also have code to check for that first call and make sure I don’t process anything if it shouldn’t.

    So here’s what I’ve known about for a long time.
    1). Codea runs thru the code twice before it executes the setup() function.
    2). Parameters in setup() that have callbacks will execute that callback when the program starts even though the parameter isn’t used yet.

    I don’t know why, but that’s what happens and that’s what I code for if I need to. I don’t think it’s ever been documented, but at some point I probably asked about it. There’s other things I’ve come across that seemed odd, but that’s the way Codea works.

    Try this code.

    function setup()
        parameter.integer("xxx",1,5,aaa)
        parameter.integer("yyy",1,5,bbb)
        parameter.integer("zzz",1,5,ccc)
    end
    
    function aaa()
        print("aaa")
    end
    function bbb()
        print("bbb")
    end
    
    function ccc()
        print("ccc")
    end
    
  • Posts: 171

    @dave1707 yep you're right, i'll leave my previous message mostly intact, but setup is not being called twice

    print("before setup")
    function setup()
        print("setup")
    end
    print("before draw")
    function draw()
      print("draw")
      -- This sets a dark background color 
      background(40, 40, 50)
    end
    print("after both")
    
    

    i guess because the parameter is being initialized in a function that is called twice?? another good reason to put loading logic into draw

  • Posts: 1,089

    a program consisting of nothing but a single print statement prints twice! why?

  • dave1707dave1707 Mod
    Posts: 9,415

    @RonJeffries Probably what Codea has to do before it can start running any code. Could be similar to a two pass compiler. To me it doesn’t matter how many times it does it because there are very few commands I put outside of any function. Currently the one I use most is “viewer.mode=...”

  • Posts: 1,277

    @dave1707 I get that it doesn’t matter to you, because over 8 years you’ve adapted your practices to accommodate Codea’s quirks.

    I don’t think that’s a good yardstick for what is expected and unexpected behavior.

  • dave1707dave1707 Mod
    Posts: 9,415

    @UberGoober Yes, I’ve adapted to Codea’s quirks because apparently that’s the way Codea works. Maybe some update will change that, and I will adapt to that. Just like the way assets are now coded. I’ve changed all my projects and I’m sure you’ve changed all your projects to account for that. Some things change and some things don’t and some thing are just the way they are.

  • Posts: 1,089

    Yes @dave1707 I agree that it's not a problem. However, it is interesting and I'd like to understand what's going on.

  • Posts: 1,277

    It's not a problem once you know about it.

    If you don't know about it's hours if not days of pulling your hair out.

  • dave1707dave1707 Mod
    Posts: 9,415

    @UberGoober Thats how you learn, or at least that’s how I learn. I keep poking around until I figure out what’s happening. That’s what I enjoy about coding.

  • Posts: 1,277

    @dave1707 sure, and there’s lots to be learned from obstacle courses, too.

    At times Codea is a fun way to make cool things, and at times it’s an obstacle course.

    It often seems like you defend difficulty for difficulty’s sake; have you ever learned something and then thought, gee, it would be great to help other people learn this more easily?

  • dave1707dave1707 Mod
    Posts: 9,415

    @UberGoober Would I help other people learn something more easily, NO. It was hard for me to learn, so it’s going to be hard for you. Past experience shows me that people who are just given things don’t appreciate them. If you don’t work for it then it has no value to you. When you break it, you expect to be given another one no matter how expensive it was to begin with. Just kidding. How was that for defending difficult for difficulty’s sake. Of course I’ll help, but I don’t know what to help with until someone asks. I try to explain things to the best of my knowledge, but I can only explain what I figured out.

  • Posts: 1,277

    @dave1707 lol you totally had me there!

  • SimeonSimeon Admin Mod
    Posts: 5,693

    I would classify this behaviour as a bug (running things twice). Codea does run the code twice, but the first pass being hooked up to the output system / UI is the bug

    I'm not sure if I'd classify executing the parameter callback on initial setup as a bug. I can't decide if the behaviour is useful or not, and technically, you could consider it a value change (the value has gone from nil to whatever the initial value of the parameter is)

  • Posts: 1,277

    @Simeon I think the rubric I suggested is useful: when you declare a button that has a callback, do you expect the callback to be run without a user pressing it?

    I think most people would say no, a button should only execute its callback when a user presses it.

    Similarly, for any piece of UI, defining what it does during interaction should not itself be treated as an interaction.

  • Posts: 1,277

    @Simeon also, about usefulness: if the programmer wants a parameter’s callback to be run at the same time the parameter is declared, that is in their control at any time; they can make that happen just by regular coding.

    But by making the callback run automatically you remove the programmer’s choice in the matter.

  • SimeonSimeon Admin Mod
    Posts: 5,693

    @UberGoober I can agree with that. Defining it should not invoke the callback

  • dave1707dave1707 Mod
    Posts: 9,415

    @Simeon I have code where I want the callback to be executed when the parameter is defined. That way things are set the way I want when the code is executed. I realize sometimes you don’t want it executed at startup, so maybe there can be a parameter that get set something like “viewer.mode=FULLSCREEN” does at the start. Something like “callback=true” to run it at definition and “callback=false” or not coded as the default, to not execute a callback at startup.

  • Posts: 1,277

    @dave1707 can't you easily make the callback execute when the parameter is defined by calling it right under where you've defined it?

  • dave1707dave1707 Mod
    Posts: 9,415

    @UberGoober But why do I have to add code to execute a callback when it executes to begin with. Why can you add code to your callback function to ignore the first callback.

  • Posts: 2,348
    I've just got used to defining the parameter variable before the parameter definition itself. Don't see the issue, other than my decaying grey matter keeps forgetting.
  • edited April 27 Posts: 1,277

    @dave1707 because it doesn't make logical sense in two ways:

    1. merely defining a function should not automatically trigger that function
    2. merely defining a UI control should not trigger that control

    Definition and execution are logically separate processes that should be explicitly separate in parameter definitions, as they are everywhere else in lua.

  • dave1707dave1707 Mod
    edited April 27 Posts: 9,415

    @UberGoober I’m used to things not making logical sense, that’s life. You adapt or you die. That’s why I suggested something that can be set at startup as to whether you want the callback to execute at definition or not.

  • edited April 27 Posts: 1,277

    @dave1707 life is extremely uninterested in logic, true. I think you maybe just demonstrated that too by criticizing the appeal to logic followed by making a very logical suggestion. ;)

  • Posts: 1,277

    @dave1707 I’m also curious how you’ve been preventing automatic execution inside the callbacks themselves, and would love it if you wanted to share example code. Honestly before even bringing this up I tried to do that many different ways and none of them worked. You saying it’s super easy was surprising to me tbh.

  • dave1707dave1707 Mod
    Posts: 9,415

    @UberGoober It doesn’t matter to me what happens to the callback. If it’s done your way, I’ll make the change, if it’s done my way, I’ll make the change. That’s what programming is all about, making changes. Your way is logical, my way is something, I don’t know what. I’ve seen plenty of changes to Codea over the years, the hardest was the change to using the asset system. That took me forever to make all the changes, but I made them.

  • Posts: 1,277

    @dave1707 I should mention something else about the specific cases I’m using parameters in.

    My project repeatedly resets the parameter list in response to user interaction, clearing it and then re-instantiating around 15+ different controls.

    It’s been a nightmare having to account for some of those controls calling their callbacks when re-instantiating item, and some of them not, and actually changing some of them also as needed.

    So any solution to preventing a callback from executing that only works by excluding the initial value won’t work in my case; they all have to be reset while retaining whatever value they’re currently set at and not calling the callback.

  • dave1707dave1707 Mod
    Posts: 9,415

    @UberGoober That makes sense. Since I don’t write anything important or that big, I don’t think I recreate the parameters list that much. If I do I probably use the callback to set something up anyways.

  • edited April 28 Posts: 2,348

    Perhaps you could include a boolean in each parameter call for enabled/disabled which defaults to enabled, but allows you to disable on running. Parameter.clear could set all to disabled or destroyed.

  • SimeonSimeon Admin Mod
    Posts: 5,693

    Given that we have a special case for buttons (parameter.action) where the action does not get fired on parameter declaration, I think it makes sense to extend this as the default behaviour across all parameter types

    In the latest build (274), parameter should no longer trigger callbacks on initialisation. Let me know if this causes any issues

  • Posts: 1,089

    makes sense to me!

Sign In or Register to comment.