NetLogo Web

NetLogo Web Differences

Please note that our goal is to implement as many of desktop NetLogo's features as is reasonably possible, so many of these "unimplemented" features are likely to eventually appear in NetLogo Web in some form or another.
  • HubNet
  • File-related primitives (for example, file-open)
  • ask-concurrent/without-interruption
  • display/no-display
  • export-interface
  • inspect
  • user-one-of
  • Many of the extensions, see the bundled extensions list
  • 3D
  • BehaviorSpace
  • Shapes Editor
  • System Dynamics Modeler

Here in NetLogo Web, import-* primitives work a bit differently from how they work in desktop NetLogo. For one, when importing a file in NetLogo Web, the string argument to the import-* primitive is accepted (out of a need for compatibility with desktop NetLogo) but ignored (due to the fact that browser-based applications cannot automatically read files directly from your computer). Instead, NetLogo Web will open up a file dialog and ask you to manually select the to-be-imported file from your file system, regardless of the value of the string argument.

Secondly, these primitives behave differently in a way that, under particular circumstances, can be surprising. In desktop NetLogo, importing a file happens "synchronously", which is to say that, if your model says to run import-world on line 10 of a 20-line procedure, NetLogo will not run lines 11-20 until after import-world has completed. In browser-based applications, though, files cannot be read synchronously. Instead, they are always read asynchronously, with line 10 of the aforementioned, hypothetical 20-line procedure now telling the browser that it should import the file whenever the browser is ready, followed by the browser immediately running lines 11-20 before actually importing that file. Once those lines have been run and the browser doesn't have anything else to do, then it will import the file.

What this translates to is that, in the uncommon case that your procedure relies on an import-* primitive executing before that procedure has ended, NetLogo Web will behave differently than desktop NetLogo, and your model might need to be re-architected a bit in order to get the two models running in the same way on both platforms.

wait is a primitive that functions significantly differently in NetLogo Web. Normal desktop applications allow programs to have multiple "threads" of code running at the same time. This is allows a program to have one thread for running heavy computations (like executing NetLogo code) and another thread that works to update what you see on your screen, to reflect the computations that have been done by the other thread (while that hard-working thread is still doing other hard work). In the browser, there's just one thread for everything (caveat: that's not strictly true, but multi-threaded browser-based programs are unacceptably slow, for the time being, at least). Since there's only one thread and don't really have the ability to suspend our current thread, switch to a different task, and come back at will, primitives like display cannot work as expected. Instead, the visualization update from display can only happen after all queued NetLogo procedures have temporarily finished running (which defeats the entire purpose of using display, anyway, because a "when the browser gets around to it" visualization update is going to happen whether display had been called or not).

This poses major problems for display, but it might not be apparent how it's a problem for wait. Well, first, because wait is most frequently used in conjunction with display, so if you can't use display, you're missing out on most of the usefulness of wait. But it also causes problems for wait directly. The thing is, since there aren't multiple threads in the browser, browsers don't give tools for blocking execution and waiting for a certain amount of time to pass before going on (which is essentially the definition of wait). Instead, they only give tools for saying, "After this much time has elapsed, and then once you don't have anything else to do, run this code." Unfortunately, that sort of execution model is incompatible with how wait is used in desktop NetLogo.

So what can we do with wait in NetLogo Web? The best thing that we can do is honestly something that a web developer really shouldn't ever do, which is to just keep our browser tab's lone thread busy with pointless work for the amount of time that we were told to wait. The upside is that it waits as long as its argument says to wait, and then proceeds to run the rest of the queued NetLogo code. The downside is that you still will not see any visualization changes until wait and the rest of the currently enqueued code has been run, plus this produces a bad user experience, because it locks up the entire browser tab and prevents interaction with the widgets, and, if the wait waits for long of enough, it could even prompt your browser to ask if you want to close this "unresponsive" tab. Unfortunately, that's about the best we can do with the tools that the browsers give us.

And please note that we don't recommend using wait, to begin with, in either desktop NetLogo or NetLogo Web. wait mostly continues to exist for backwards compatibility with models made before NetLogo's modern idioms were settled upon. Ultimately, you can almost always work around the need for wait in a way that is less likely to cause problems, more idiomatic to NetLogo, and that will work in NetLogo Web. The only exception is when you really want to wait until a number of seconds have passed on your clock before doing something. And that's "almost never".

One of the problems that using wait can cause, even on in desktop NetLogo, is that it can end up making a model perform differently on different computers. So if you try to use wait to control animation speed, a use of wait 0.1 might cause the animation to look good on your computer while also making the program unpleasantly slow on older, lower-performance computers, and simultaneously too fast on, for example, newer, more-powerful computers that might come out after yours, because the wait takes the same amount of time on each machine, but the other bits of NetLogo code won't, so they might require a wait 0.01 or a wait 0.2 in order to get the same visual effect. The proper, "works on all computers" way for varying the speed of a NetLogo model is to simply adjust the "speed" slider as necessary.

So what can you do to make idiomatic NetLogo models with well-timed animations? One might be tempted to use every, and that could "work", but it would also have most of the same problems as wait. Instead, the best option to build little "state machines" out of global variables, where your go is run in a "forever" button, and each iteration of go changes the global variable to set the animation state, like this: