Board index FlightGear Development Aircraft Systems

A general approach to systems modeling in Nasal

Modeling aircraft systems, like electrical stuff, hydraulics, pneumatics? Feel free to ask support.

A general approach to systems modeling in Nasal

Postby galvedro » Fri Nov 01, 2013 6:33 pm

Hi!

As a continuation of the work I started with the soaring instrumentation sdk, I have been looking into refactoring the library for general use in systems modeling. After some digging, I believe the way to go for now is to create a signal processing library in Nasal using the same component based architecture I used for the soaring sdk.

Here is a prototype script implementing a basic electrical system. You may recognize this layout from Buckaroo's documentation. I took his framework as the "state of the art" in generic electrical systems for Nasal. Note that this is only a signal processing pipeline where the signal is "volts", it doesn't simulate output loading in any way (yet).

Code: Select all
io.include("Aircraft/Generic/Systems/signal-processing.nas");

# Trivial generators for now

var alternator = { output: 15 };
var battery = { output: 12 };

# Circuit configuration

var alternator_sw = Switch.new(
    input: alternator);

var battery_sw = Switch.new(
    input: battery);

var bus = MaxInput.new(
    inputs: [alternator_sw, battery_sw],
    on_update: update_prop("systems/electrical/volts/bus"));

var starter = Switch(
    inputs: [bus],
    on_update: update_prop("systems/electrical/volts/starter"));

var landing_lights = Switch(
    inputs: [bus],
    on_update: update_prop("systems/electrical/volts/landing-lights"));

var panel_lights = Switch(
    inputs: [bus],
    on_update: update_prop("systems/electrical/volts/panel-lights"));

var electric_system = UpdateLoop.new(
    components: [alternator_sw, battery_sw, bus,
                 starter, landing_lights, panel_lights],
    update_period: 1 / 10);

# Connect switches to their controlling properties

var switch = func (sw) {
    func (prop) { sw.on(prop.getValue()) }
};

setlistener("systems/electrical/switches/alternator", switch(alternator_sw));
setlistener("systems/electrical/switches/battery", switch(battery_sw));
setlistener("systems/electrical/switches/starter", switch(starter));
setlistener("systems/electrical/switches/landing_lights", switch(landing_lights));
setlistener("systems/electrical/switches/panel_lights", switch(panel_lights));
galvedro
 
Posts: 145
Joined: Mon Oct 07, 2013 1:55 pm
Location: Sweden

Re: A general approach to systems modeling in Nasal

Postby Hooray » Fri Nov 01, 2013 7:58 pm

That looks also pretty clean and readable to me, especially for a first iteration!

I think this is one of those cases where we may need several iterations to cover the most important use-cases for different purposes/aircraft. For example, I'd imagine that some simple form of "typing" could be useful here - as in having a type for "voltage", so that the library/framework can determine if people are mis-using it. A simple typing framework could be built on top of Nasal hashes, where we'd expect outputs/inputs to be of a certain type and only allow certain combinations, and provide an error message otherwise.

Over time, additional types and units could be added (e.g. for pressure), possibly also for different types of currents (AC/DC).

Also, I would think that some integrated debugging mode would be incredibly useful here for people using the framework to develop/port their systems to visualize their work - i.e. using Nasal's logging facilities. If each component/element can be traversed recursively, it would also be trivial to visualize such systems using a canvas-based GUI dialog, and using some meta information for text labels.

We also need to come up with some form of failure-mode at the framework level, so that the soaring SDK (and other systems) can provide support for failing certain equipment, ideally not just from Nasal-space, but via properties - so that instructor/student scenarios can be realized using the built-in httpd/telnetd networking support.
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: A general approach to systems modeling in Nasal

Postby Philosopher » Fri Nov 01, 2013 8:21 pm

Hi again! You're back :)

Your approach is as consistent as last time, but even more pseudo-code-ish, I suppose ;) (with the addition of switch(), I mean). Adding to Hooray's comments, I would suggest that as your systems, like the one you displayed above, get more complicated it might make sense to move this to XML-space (i.e. have some form of interpreting layer to take a PropertyList XML syntax and convert it to the code you have above). As David Megginson once said, it makes sense for Nasal to contain the "verbs" (i.e., it acts on data) while XML has the "nouns" (i.e., it represents the data that Nasal works off of), and that would be applicable here too, if you want to take the time to do so (you certainly can keep on the Nasal route, but I always feel that XML's tree structures are better for visualizing complex data).

Apologies since I'm rather busy this week and can't review your merge request, but I do say that it looks good to me. I think we need to talk with James to see if he's OK with this, but it should work out fine. We will need to squash the commits before pushing, though ;).
Philosopher
 
Posts: 1593
Joined: Sun Aug 12, 2012 7:29 pm

Re: A general approach to systems modeling in Nasal

Postby Hooray » Fri Nov 01, 2013 8:48 pm

Funny, I also thought about mentioning that XML should be favored over Nasal for declaration of complex systems, but didn't want to overwhelm you - on the other hand, the XML helpers are also in io.nas, so it's just a matter of building the corresponding Nasal data structures based on traversing a property tree - all the PropertyList-XML parsing is handled by internal C++ code, see: read_properties() in io.nas

PS: For the sake of completeness and to explain Philosopher's comment: David Megginson is one of the "rock stars" in FG lingo, because he designed the property tree system originally (with Andy Ross being the Nasal designer/rock star).
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: A general approach to systems modeling in Nasal

Postby galvedro » Fri Nov 01, 2013 10:50 pm

Personaly, I think scripting can be used very effectively in a "declarative" style, covering the same ground as xml while being both more readable (i.e. maintainable) and flexible. But perhaps you are right and in the end, xml ends up being the right choice. We will need to experiment a bit.

For now, I am focusing on simplicity and flexibility. One of the strengths of the current model is that it is not domain specific, i.e. you can connect any block with any other however you like and it just works. Its very much like a Lego brick approach. Now, the key is to come up with the right bricks to be included in the kit :D

Regarding failure modes, I think they fit naturally in the signal model, by considering "serviceable" an input signal that controls the relevant failure behavior (if that makes sense). I have not implemented any yet, but I don't think they will be a problem.
galvedro
 
Posts: 145
Joined: Mon Oct 07, 2013 1:55 pm
Location: Sweden

Re: A general approach to systems modeling in Nasal

Postby Hooray » Sat Nov 02, 2013 4:26 pm

I also don't think that supporting XML is going to be very important very soon - your code is generic and flexible enough in its current form, so that supporting XML should be fairly straightforward.

That being said, there are obviously some fairly sophisticated aircraft with complex systems in FlightGear - not just airliners, but also some of the smaller jets.

Scripting such huge systems is usually pretty awkward, even if it's just from a long-term maintenance standpoint.
Visualizing such scripted systems in a GUI is going to be difficult, unless you have a full Nasal parser, or unless you are using a subset of Nasal (think JSON/Nasal hashes) to declare systems and their relationships.

Thus, your current approach, of identifying low-level building blocks and building more complex components on top of these, would seem pretty useful - and it should be straightforward to also expose this to PropertyList/XML-space eventually (if necessary). In general, complex systems are usually designed in declarative languages, not necessarily real code.

just to provide a little context:
You only need to take a look at some of the more sophisticated aircraft/systems simulations in FlightGear - they're often incredibly messy, either because of huge portions of specialized C++ code, or because of tons of scripted spaghetti code. The really unfortunate thing is that other aircraft developers often tend to adopt such systems by using a copy/paste "programming" approach, so that we often end up with even more code that's hard to maintain in the long run. Which is why your current systems modeling approach is so much superior.

We also have some custom-scripted FDMs, and usually the XML-approach is more future-proof - because there's less room for screwing up for people who are not formally trained in programming (or who don't have any significant programming experience otherwise). On the other hand, sometimes there's no way around custom-scripted code, simply because existing C++ systems don't have the required scripting hooks.

Originally, we didn't have Nasal scripting capabilities, which is why XML files ended up with supporting conditions, command bindings and fgcommands etc - but in the meantime, scripting can usually be considered superior, unless something is really performance-critical, or unless we have existing hard-coded systems that can be used, or which can be equipped with scripting hooks.

We used to have a few discussions about implementing custom autopilots in Nasal - which is obviously possible, but also requires lots of duplicate code in the end (because we do have a highly sophisticated and highly configurable hardcoded C++ system doing that) - but people still ended up using scripted code, because the autopilot system isn't yet exposed to scripting space - but in general, it is better to use the hard-coded autopilot system - its maintainer was meaning to provide the corresponding bindings at some point, but didn't really get around to it obviously. Meanwhile, we have the cppbind framework, which should simplify the whole job. This is just another example why scripted code is sometimes preferred by contributors, who don't have access to C++ code, or who cannot easily build custom FG versions.

Likewise, there are some exceptions like the AI traffic system or the route manager, neither of which are fully exposed to scripting space currently - so that certain workarounds need to be made in order to still use these features (imagine scripted AI traffic, AI traffic with custom FDMs or AI traffic using autopilots or the route manager), but in general, it's a good idea to keep in mind what's possible already, but also what effect certain approaches will have on the FG developer community as a whole - we have some fairly massive systems simulations coded entirely in Nasal by highly dedicated aircraft developers, just because the state machine stuff isn't currently exposed to scripting space. Some of the most-developed airliners are pretty messy from a Nasal point of view, and do have a fairly noticeable impact on framerate, too.

Regarding failure modeling, you should be aware that we have a "failures.nas" script, and another "mtbf.nas" script somewhere - and someone was actually looking at integrating those with the tutorial system (which is also 100% Nasal).
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: A general approach to systems modeling in Nasal

Postby galvedro » Sun Nov 03, 2013 11:29 pm

Hooray wrote in Sat Nov 02, 2013 4:26 pm:You only need to take a look at some of the more sophisticated aircraft/systems simulations in FlightGear - they're often incredibly messy, either because of huge portions of specialized C++ code, or because of tons of scripted spaghetti code. The really unfortunate thing is that other aircraft developers often tend to adopt such systems by using a copy/paste "programming" approach, so that we often end up with even more code that's hard to maintain in the long run.


:lol: That is a big problem indeed, and is actually a very good reason for favoring an xml approach: to provide a customization mechanism for people not familiar with programming. As you said, I also think it will not be a problem to eventually provide such an interface on top, so you end up with two layers: a limited interface based on static xml setups, and a full interface in Nasal for the adventurous.

All in all, from your post, I extract one bold conclusion: there is a need for a library of properly programmed modules in Nasal so contributors don't need to do all by themselves. Those modules might be either bindings to objects implementing complex functionality in the C++ core, or other Nasal modules engineered on purpose for reuse.

Meanwhile, I continue to explore the modeling possibilities of what we have already. This snippet implements basically the same static system that is currently hardcoded in C++. This time, I include a basic failure mode for completeness.

Code: Select all
var probe = PropertyReader.new("/environment/pressure-inhg");
var pressure = Dampener.new(
    input: probe,
    dampenig: 1,
    on_update: update_prop("/systems/static/pressure-inhg"));
   
var static_system = UpdateLoop.new(
    components: [probe, pressure]);

setlistener("/systems/static/serviceable",
    func (prop) { probe.scale = prop.getValue()? 1 : 0 });


EDIT: posted before finished..
galvedro
 
Posts: 145
Joined: Mon Oct 07, 2013 1:55 pm
Location: Sweden

Re: A general approach to systems modeling in Nasal

Postby galvedro » Tue Nov 05, 2013 9:33 am

The more I think about it, the more I am leaning towards unifying the different system modeling blocks in the C++ core under a generic interface that is exposed (or linked in some way) to Nasal. Think the PID controller, the different filters, flip-flops, etc. They are not substantially different to the basic bricks I am writing...

The basic idea would be to detach those blocks from their specific application (autopilot, for example) and refactor them into an independent library with bindings in Nasal and a similar interface to what I have been showing so far. The end result would be quite simulinkish in flavour. It is already starting to smell a bit to that actually... :D

An architecture like that would eventually enable three possible approaches to system modeling: low level C++, static xml driving C++ underneath and fully scripted Nasal. Sounds too ambitious?
galvedro
 
Posts: 145
Joined: Mon Oct 07, 2013 1:55 pm
Location: Sweden

Re: A general approach to systems modeling in Nasal

Postby Hooray » Tue Nov 05, 2013 11:42 am

galvedro wrote in Tue Nov 05, 2013 9:33 am:The more I think about it, the more I am leaning towards unifying the different system modeling blocks in the C++ core under a generic interface that is exposed (or linked in some way) to Nasal. Think the PID controller, the different filters, flip-flops, etc. They are not substantially different to the basic bricks I am writing...


Note that "static XML" isn't all that static in the cause of the AP system - it makes heavy use of so called "Tied Properties", which are basically "live" properties, properties linked to C++ variable. The more modern, and more future-proof approach is using so called SGPropertyChangeListener or so called "PropertyObjects"- which is basically a C++ template class that may subscribe to property tree events and which gets called subsequently to update internal state - you'll find that this is used by subsystems like the AP or the AI Traffic system: there's sort of an API modeled on top of properties and the property tree - which is why the configuration may be considered "static", but it's often using "live" properties and therefore pretty dynamic.

The appealing thing here is that the API is automatically exposed to all property frontends - not just Nasal scripting via setprop/getprop etc - but also the property browser, the built-in httpd daemon - but also the telnet/props server, which makes it possible to "remote-control" FlightGear in an RPC fashion.

The canvas system makes extensive use of these listeners for modeling a whole 2D drawing API on top of the property tree

The basic idea would be to detach those blocks from their specific application (autopilot, for example) and refactor them into an independent library with bindings in Nasal and a similar interface to what I have been showing so far. The end result would be quite simulinkish in flavour. It is already starting to smell a bit to that actually... :D

An architecture like that would eventually enable three possible approaches to system modeling: low level C++, static xml driving C++ underneath and fully scripted Nasal. Sounds too ambitious?



Yeah, it does sound ambitious - not necessarily too ambitious though. You would obviously need to be able to build FG from source, because that would no longer touch "just" Nasal code.

A while ago, Philosopher also suggested something along these lines, he came up with the idea to implement SimGear's SGSubsystem class as a Nasal/cppbind binding, so that FGData/Nasal contributors would ideally follow the SGSubsystem approach and implement the required interfaces/methods (analogous to C++ devs) - what we're currently seeing is lots of listeners and timers being used instead to implement "pseudo subsystems" in Nasal, which is not too easy to control in terms of certain simulator events (restart, suspend, reset/re-init etc).

It would seem possible to generalize the SGSubsystem/SGChangePropertyListener approach such that subsystems would also expose scripting bindings (optionally).

Originally, SGSubsystem was intended to be the common interface for all subsystems, but that was over a decade ago - we still have a bunch of subsystems that don't really use it.

http://docs.freeflightsim.org/simgear/c ... ystem.html
http://simgear.sourceforge.net/doxygen/ ... ystem.html

In the meantime, it would indeed be possible to expose such FG/SG building blocks thanks to TheTom's cppbind framework, which is to be found in simgear/nasal/cppbind: https://gitorious.org/fg/simgear/source ... al/cppbind

Tom's cppbind framework makes heavy use of modern C++, so that C++ data structures and classes/methods can now be easily exposed to Nasal space and vice versa.

Implementation examples are to be found in $FG_SRC/Scripting: https://gitorious.org/fg/flightgear/sou ... /Scripting

For example, see the most recent addition, which is exposing SimGear's HTTP client code to Nasal space with less than 140 lines of code:
https://gitorious.org/fg/flightgear/sou ... alHTTP.cxx

There's still plenty of "old" code that doesn't yet use the cppbind framework - check the header inclusions at the top of the file.

Regarding things like the PID controller code, its developer/maintainer (Torsten) was actually planning on making this stuff accessible from Nasal, just to prevent scripters from implementing APs in Nasal (due to garbage collection issues) - so that should be a no-brainer actually, and such work should be appreciated:

Subject: 2 Questions: vacuum & electrical

Torsten wrote:I think, performance of Nasal code and XML based property rules is pretty close. The big advantage of the property rules is that they don't produce garbage that a garbage collector has to clean up. But as nothing in life comes for free (except FlightGear, of course) XML tends to be much more verbose - as you correctly stated.

My personal guideline for using one or the other system is:
  • Computing properties from a well defined set of other properties once per frame: use a property rule.
  • If there is no other way to get it done: use Nasal.

Torsten wrote in Thu Feb 02, 2012 10:08 pm:especially if these configurations could be instantiated at run time

Great minds think alike. I have recently committed some code to allow runtime loading of <strike>autopilots</strike> property rules and have a Nasal binding for that in mind. This _might_ end up in something like
Code: Select all
var myPid = pidController.new();
myPid.Td = 0.0001;
myPid.Ti = 123.4;
myPid.Kp = 0.2;
myPid.input = "/foo";
myPid.reference = "/bar";
myPid.output = "/baz";

etc, etc.

But that's probably a little off topic now.
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: A general approach to systems modeling in Nasal

Postby galvedro » Tue Nov 05, 2013 1:53 pm

Thank you for the pointers Hooray, this is very good background information.

Hooray wrote in Tue Nov 05, 2013 11:42 am:the configuration may be considered "static", but it's often using "live" properties and therefore pretty dynamic.


Yes, by "static" I only meant in contrast to "fully scripted" really, nothing else.

Hooray wrote in Tue Nov 05, 2013 11:42 am:Yeah, it does sound ambitious - not necessarily too ambitious though. You would obviously need to be able to build FG from source, because that would no longer touch "just" Nasal code.


Yes, sure! I have managed to get my development environment up at home, and I am now able to build FG again. I think what I am going to do is to grow a little library in a sandbox (i.e. not interacting with the main code) by borrowing exiting components, and do some experiments with the cppbind framework. I have seen the cppbind code, and it looks really nice indeed!

I will do that in a separate branch, as it is highly experimental stuff, and I will continue with the generic Nasal-only approach in parallel, so I don't get stuck in a dead end. Hopefully both approaches will meet somewhere along the way :D
galvedro
 
Posts: 145
Joined: Mon Oct 07, 2013 1:55 pm
Location: Sweden

Re: A general approach to systems modeling in Nasal

Postby Hooray » Tue Nov 05, 2013 2:09 pm

Just for the sake of completeness, there's also an old wiki tutorial that describes the low-level Nasal C APIs, while these are now fully abstracted away by TheTom's cppbind framework, it may still be useful to have a quick look, to understand the underlying Nasal building blocks: http://wiki.flightgear.org/Howto:Extend_Nasal

You will find that most of the "old" code in $FG_SRC/Scripting still uses those C-APIs for interacting with the Nasal engine. Only the new code, #include'ing <simgear/nasal/cppbind>, uses boost templates to hide the low level details.

Most of the code in the Nasal subsystem itself (FGNasalSys) also still uses the legacy C APIs - this is just to explain the two approaches, to avoid unnecessary confusion.

Also, you'll find some more terminology explained in the wiki tutorial, especially for things like "Nasal Ghosts" - which are basically C-style pointers that can point to arbitrary data structures, and that are explicitly mapped to corresponding malloc/free implementations.

Additionally, Philosopher has created a rather technical write-up covering the internals of the Nasal engine, I don't have the link at the moment - but we were planning to get it committed to fgdata anyway.

Overall, I suggest to favor cppbind over the low-level approach, it isn't only much more elegant, but also saves you tons of typing, too :D

Some of the more straightforward things to play with would be exposing useful SG/FG classes to Nasal space, such as the SGSubsystem interface to register scripted SGSubsystems, or the autopilot system.

For more technical Nasal questions (C API, internals etc), you'll probably want to refer to Philosopher, TheTom, Zakalawe or myself - TheTom and Zakalawe can also provide help on using cppbind, having both used it extensively during the last months.
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: A general approach to systems modeling in Nasal

Postby galvedro » Thu Nov 07, 2013 6:31 pm

I have been doing some very basic performance tests. I haven't seen these figures anywhere, so I will post them for anyone interested :wink:
I am comparing different (elementary) mechanisms for communicating two objects in Nasal. The baseline metric is the time it takes to read a constant, i.e. var myvar = 25 takes one "performance unit".

Code: Select all
Constant assignment
var myvar = 25;
---------------------------------------------> 1 p.u.

Reading a hash table member
var myvar = h.member;
where h = { member: 25 };
---------------------------------------------> 1.1 p.u.

Reading a vector member
var myvar = array[1];
where array = [25, 25, 25];
---------------------------------------------> 1.2 p.u.

Function call
var myvar = get();
where get = func { 25 };
---------------------------------------------> 2.9 p.u.

Property read (getprop)
var myvar = getprop("/sim/speed-up");
---------------------------------------------> 3.1 p.u.


So, for the performance aware minds out there, reading a member from a (small) hash is about the same as reading a constant (perhaps because they are also contained in a hash, i.e. the local namespace?). And calling a nasal function to get a value takes about the same as reading a property using "getprop".

The last one I didn't expect, although it definitively makes sense. I thought reading properties would have had more cost. It's always a good idea to take some measurements! :D
Last edited by galvedro on Thu Nov 07, 2013 6:56 pm, edited 1 time in total.
galvedro
 
Posts: 145
Joined: Mon Oct 07, 2013 1:55 pm
Location: Sweden

Re: A general approach to systems modeling in Nasal

Postby Hooray » Thu Nov 07, 2013 6:39 pm

Yeah, I think Thorsten once posted several benchmarks (Thorsten, is the guy who developed an entire weather simulation in scripting space, that ended up being superior to anything that FG ever had had before). Philosopher has customized his SG/Nasal branch such that it actually does profile lowlevel op codes - otherwise, you can use systime() or debug.benchmark()

If you are interested in Nasal performance, check out Philosopher's article at: http://wiki.flightgear.org/User:Philoso ... n_findings

Regarding your final conclusion: getprop() is indeed heavily optimized, it is much faster than the props.nas helpers currently - but that may change once the cppbind framework replaces props.nas bindings (another thing that Thorsten figured out).

Also note that Nasal does support background threads (real threads), however only Nasal itself is threadsafe - none of the FG APIs are.
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: A general approach to systems modeling in Nasal

Postby galvedro » Thu Nov 07, 2013 7:10 pm

Yes, I think read those. I remember a comparison between the getNode and getprop family, being getNode like 10x times slower or something. I was just curious about how the different Nasal structures compared to each other in terms of performance.

The figures above should be reasonably accurate. They are taken with systime() around a 10,000,000 turns loop performing each operation.
galvedro
 
Posts: 145
Joined: Mon Oct 07, 2013 1:55 pm
Location: Sweden

Re: A general approach to systems modeling in Nasal

Postby Philosopher » Fri Nov 08, 2013 4:59 am

galvedro wrote in Thu Nov 07, 2013 7:10 pm:The figures above should be reasonably accurate. They are taken with systime() around a 10,000,000 turns loop performing each operation.

Sounds like more than two sig digs to me! ;) Excellent reasearch, how long does it take to run the tests, and is it one single script?

One thing I would like to do at some point is compile a list of tests like these and publish results. Yours is a good start, but I'd like to include more practical use cases (e.g., more than one member ;)), and possibly even full, working snippets both before and after serious optimization (i.e. as better illustrations of what to do, what not to do). Currently I have some snippets with things that should work (aka short regression tests) and shouldn't work (including what error they give), just as sort of an intro to Nasal features and documentation of niches (like `{member:}` and `{member1:,member2:}` being legal syntax, while `var a;` isn't). I think I'll make a Gitorious repo for this and add y'all & macnab as committers – one day, that is ;).
Philosopher
 
Posts: 1593
Joined: Sun Aug 12, 2012 7:29 pm

Next

Return to Systems

Who is online

Users browsing this forum: No registered users and 0 guests