Function Overloading in AS3
Why doesn't AS3 have function overloading
If there is anything I hate more than when actionscript doesn't do something I wish it would, it is when people complain about something they wish it would do. Sure, it would be nice if it incorporated every programming concept ever but that just isn't going to happen. In fact, this point is the same for every language out there. It sure would be nice if they all did everything but then there would only be syntacticular differences and that would be silly. Anyway, actionscript does not natively offer function overloading, and I've heard and/or read people complain about that from time to time.
Roll your own
Usually the reason you wish a solution existed natively is because you've used it before and you'd like to have the same ease writing the code. At least, if we follow the premise of not pre-optimizing code. So, if a language doesn't have that construct what do you do? Either find an alternate or roll your own. Today we are going to roll our own method for overloading functions in AS3 to allow for some of the benifits of native function overloading.
This isn't my idea
I have to admit, this isn't my idea. Back in the days of AS2, there was one library that did a lot of rolling its own solutions to constructs actionscript didn't provide. That library was as2lib by Simon Wacker and Martin Heidegger. I remember just reading the as2lib source code to learn different ways of doing thing. They had a solution for function overloading that I used as a basis for the AS3 code. I figured, AS3 had better reflection and introspection (as2lib had libraries for that as well) than AS2 so this should be fairly easy. In some ways it was and in some was it wasn't. That's a good thing because I learned a few things along the way.
Enough typing, where's the code
The code I wrote to allow this functionality is available at github. Usual rules apply, this code is just a proof of concept, for educational purposes only. Though I've written some tests, I make no guarantees.
Sample Usage
Sample usage is available in the Main.as file on github but I'll provide you with a taste here.
private function aFunction(... args):* {
const overloader:Overloader = new Overloader();
overloader.addHandler([String, Number], onStringNumber);
overloader.addHandler([String], onString);
overloader.addHandler([Number], onNumber);
overloader.addHandler([int], onInt);
overloader.addHandler([uint], onUint);
overloader.addHandler([Boolean], onBoolean);
return overloader.process(args);
}
private function onInt(value:int):void {
trace("We got int: " + value);
}
private function onUint(value:uint):void {
trace("We got uint: " + value);
}
private function onBoolean(value:Boolean):void {
trace("We got Boolean: " + value);
}
private function onNumber(num:Number):void {
trace("We got number: " + num);
}
private function onString(str:String):void {
trace("We got string: " + str);
}
private function onStringNumber(str:String, num:Number):void {
trace("We got string, number: " + str + ", " + num);
}
// then to use the overloaded function
public funciton Main(){
aFunction("Hello World", 13); // output: We got string, number: Hello World, 13
aFunction(1 == 0); // output: We got Boolean: false
aFunction(13); // output: We got uint: 13
aFunction("Goodbye"); // output: We got string: Goodbye
}
A couple notes and gotchas that you might be wondering about as you look at this code.
- Numerical arguments are automatically converted to any numerical class asked for, as long as the value can be of that type.
- For this reason I made it test numerical explicitness in the following order: uint before int and int before Number.
- Therefore if their are two matching functions due to numerical parameters a method using uint will be considered more explicit than a method using int or number.
- You can't force a numerical type. I tried several methods and none worked.
- For this reason I made it test numerical explicitness in the following order: uint before int and int before Number.
- If your overloaded function returns void you will need it to return * so it will compile without error.
- EDIT: not true, just don't use a return statement
- Because AS3 uses method closures most of the time, instead of anonymous functions, you usually don't have to worry about function scope. This is mostly a good thing. Watch out if you do use an anonymous function though. It will most likely work correct but there are a few ways it could fool you.
- I wanted to do introspection on the method signatures so you didn't have to send in the values but, alas, method signatures do not seem to be available via reflection. From what I could figure out from studying the Tamarin code, they are part of the functions Trait object which isn't available from actionscript (and may go away in the future according to the documentation). This means you have to put them in as Arrays.
Not True Overloading
Okay, so this isn't true overloading but it gets us a little of the way there. The only solutions available online use the ellipsis (...) method but you still have to write the boilerplate logic to provide type checking. Also, what happens if there is no match? With my code you at least get an error telling you what went wrong. It isn't compile time but it can help with debugging.
Also, look at what this solution actually provides. It doesn't have to be used for function overloading. It could be used anywhere you want to handle differing types of data passed in as arguments. I could envision this helping to trim down some nasty if and/or switch statements. Take a look and see what it could do for you.
Conclusion
I find the Function class and Function objects fascinating in actionscript. Back when I dug into the different types of Delegate classes for AS2 (I actually made a similar one for AS3 at one time) I learned a lot about the language as a whole. Scope used to be the bane of my existence and then I finally understood it. Scope may not be an issue anymore in AS3 but there is still quite a bit to learned about the language from studying Function objects. The very fact that a Function is an object that can be passed around in actionscript is a very nice thing. Not all languages allow that type of functionality. I guess if you are using those, you'll have to roll your own function passing solution.
Setting up Resource Bundles
In last week's Flash Friday post I wrote about using resource bundles to handle embedded fonts. I also left out any instructions about how to set up your project to use resource bundles, instead telling the reader to search the interwebs. I also said I would provide one of my own instructions so here it is.
In last week's Flash Friday post I wrote about using resource bundles to handle embedded fonts. I also left out any instructions about how to set up your project to use resource bundles, instead telling the reader to search the interwebs. I also said I would provide one of my own instructions so here it is.
Project Setup
Your project needs to be able to find your resource bundles so they need to live in your source path. You could place the bundles in the same folder as your source code, but I find that feels a little disorganized. Instead create a folder for your resource bundles and add it to your source path.
In other tutorials they talk about using resource bundles for localization. If that is the case you can add the files as follows. I'll assume you are using the en_US locale, otherwise replace all instances of en_US with the locale you are using.
- create folder path in your project of: localeen_US
- add the source folder locale{locale}
- add the following to your compiler arguments: -locale=en_US
Now you can place your resource bundles in the localeen_US folder.
Property Files
Resource bundles are sometimes referred to as property files because you create them in files with a .properties extenstion. The part before the extension is the bundle name, and you would use that to get the information you wanted. For example, you you had a bundle named fonts you would create a file called fonts.properties. If you were paying attention to my previous article you probably saw me use this same bundle name.
Inside the property file
The property file is fairly simple. It is just a key/value pair separated by an equal sign(=). A simple resource bundle that stores text strings might be called text.properties and look like the following.
# text.properties hello=Hello World! goodbye=Good-bye cruel world!
You can look back at my font embedding article to see how I embedded fonts. You can use the same method to embed anything that you can embed using the Embed metatag.
Using the properties in the file
The first thing you need to do is add the Resource Bundle metatag somewhere in your project. You only need to use it once per project for every bundle you are going to use. However, once you do this it gets compiled into the project, even if you don't use the resources. So I would recommend using it in the class(es) that use(s) the bundle.
[ResourceBundle("fonts")] public class MyFontsBundleUsingClass { ...
Then to use the resources you just need to get an instance of the ResourceManager use one of its functions to get the resource. Here is an example for grabbing a String from my text.properties file I created earlier.
var resources:IResourceManager = ResourceManager.getInstance(); var hello:String = resources.getString("text", "hello"); var goodbye:String = resources.getString("text", "goodbye");
- Of course you can get more than just strings from a property file. Just choose from the following list of functions in the IResourceManager interface.
- getString
- getBoolean
- getInt
- getUint
- getNumber
- getStringArray
- getClass
- getObject
And that is my basic primer on using ResourceBundles in actionscript projects. In the grand tradition of this line of posts I am leaving out many important bits of information. Loading resource bundles at runtime is one of them. I'll leave that as a web search exercise for the reader until I write an article on that in the future. If there are other bits of information you would like clarity on let me know in the comments.
Under the mask but I didn't ask - Flash Friday
Masks in the flash IDE are an interesting thing. You may have noticed that masks created in the IDE are not found in the normal "mask" property found on a movieclip. This is because it isn't a normal mask. The mask is working on a layer instead of on a single DisplayObject. This little quirk causes some interesting behavior that you may never have noticed before. If you have a MovieClip with a mask as a top layer of the timeline there is some strange behavior when you addChild to that MovieClip. The added content gets placed under the mask. Wait! What? The added content gets placed under the mask. You may not have noticed this behavior in the past because you may never have done it, you may not have your item cut off by the mask or you just might not have been able to figure out why you couldn't see your item. However, it is happening. [ad#Google Adsense] Another twist on this phenomenon is that if the mask isn't the top layer but your remove the items that are on the top layer then add a DisplayObject. Well, in that scenario your new DisplayObject is also placed under this "Layer Mask". I found this out today when I had a top layer above a mask that was a TextField. For a localization project I'm working on I had to wrap the field in a wrapper class that then gets added back where the textfield was. I was trying to figure out why the textfield was now appearing like it was under the mask. The answer...because it now was.
So how did I deal with this? How can you deal with this if you find it happening? First off, it might be an easy thing to just restructure your timeline so the mask isn't on top. If that isn't possible, the hack easy fix is to add a blank MovieClip symbol to the layer above the mask layer. That is what I did for this asset and all is well.
I haven't extensively tested this but my guess is the quirk may exist if you add something to any layer right above a "Layer Mask" it will placed under the mask. Is this something you have experienced? How have you worked around it? Have you used it for any type of effect?
I don't believe you really want to count on this behavior for anything as I don't believe I've seen it documented anywhere. Someone at Adobe might read my blog :) and decide this isn't appropriate behavior they might fix it in Flash Player 20 or something.
Flash Friday - Robotlegs Context
A few weeks back I wrote an article saying that I was just starting to work with AS3 Signals and the Robotlegs framework at my new job. Since then I have written a post about AS3 Signals and now it is time to write about Robotlegs. Since there is so much to write about with regards to Robotlegs I had to break out one chunk to discuss.
In working with the framework, reading lots of documentation and finding it central in the diagram above, I thought it best to start with the Context class in the Robotlegs framework.
Robotlegs is an MVCS framework similar to Pure MVC that relies on metadata based dependency injection. On the surface the first cool thing is that you can use the Inject metatag to populate class fields automagically. More automagic part of the framework is that mediators automatically get created when the view they are mediating gets added to the stage. Finally it has a very elegant central event dispatcher and Command pattern model that you barely need to do anything to get working. All this is possible because of the Context.
Getting [Inject] to work
// It really is just this easy [Inject] public var obj:MyClass;
Most of the power of Robotlegs comes from the use of the Inject metatags letting the framework. However, the framework can't inject anything until it knows what to inject. This is almost entirely done in the Context and I am going to go through the main functions here. Keep in mind that all these methods also have their inverses to undo these acts but I'll let you look those up on your own. For now I'll keep it simple and we can get to more advanced usages in other articles.
Injector methods
injector.mapValue is used when you already have a class instantiated and you want to use that object as a singleton in this application context. The basic format is: injector.mapValue(whenAskedFor:Class, useValue:Object) and might look like this:
var myObject:MyClass = new MyClass(); injector.mapValue( MyClass, myObject );
If you want to do something similar without first instantiating the object, you can use mapSingleton. The format for that is: injector.mapSingleton( whenAskedFor:Class ) and the above example would be changed to this.
injector.mapSingleton( MyClass );
injector.mapClass is used when you want the injector to create a new instance of a class every time it is asked to inject that class somewhere. The format for this function is injector.mapClass( whenAskedFor:Class, instantiateClass:Class ) and if we decided against using a singleton for MyClass instances the above examples would become:
injector.mapClass( MyClass, MyClass );
That last one may seem wierd because you type MyClass twice. However, this is because you could pass in any class that extends MyClass for the instantiateClass parameter ( or implements it if it were an interface ).
Once you've used one of these 3 commands ( or some of the others I can talk about at another time ) on all the values you want to inject in your application, anytime the framework creates or manages a class object it will have the information it needs to do just that. So how do you go about getting Robotlegs to create a class object? Automagic mediators are a perfect example.
Automagic Mediators
In Pure MVC like architectures the Mediator classes handle communication between their views and the rest of the application. Since Robotlegs is an MVCS framework based on Pure MVC this is a perfect opportunity to have the framework create the mediator for you. From the Context class you only have to write something similar to:
mediatorMap.mapView( MyView, MyViewMediator );
In this MyView is a view class and MyViewMediator is the mediator designed for it. Now the application will automagically create a MyViewMediator object when any MyView object is added to the stage and inject a reference to the MyView object into it. It will also destroy the MyViewMediator object just as magically when the MyView object gets removed from the stage. I can write much more about this in an article on the Mediator/View relationship that I plan to write in the near future.
Since Robotlegs creates the mediator it can easily inject what it needs to after it creates the class. Another class type that Robotlegs creates are Command classes.
Events, Commands and tying it all together
Robotlegs uses a centralized event dispatcher throughout to keep the model, view, controller and service sections decoupled from each other and yet tying them together at the same time. One major part of the centralized dispatcher is triggering Commands. If you've read this far, I thank you and I'm guessing you already know about the Command pattern.
To set up the command pattern in the your Robotlegs Context class just use the following format. commandMap.mapEvent( eventType:String, commandClass:Class ) which might look like this:
commandMap.mapEvent( MyCustomEvent.SOMETHING_IMPORTANT, DoSomethingImportantCommand );
Now, whenever a class in the framework dispatches the SOMETHING_IMPORTANT custom event the DoSomethingImportantCommand will be created and executed. As a bonus, the specific instance of MyCustomEvent can be injected into the command with a single line:
[Inject] public var event:MyCustomEvent;
Conclusion
So this article did not have had any sexy embedded SWF files that use Robotlegs. However, this framework's strength is not about sexy SWF files but its ease of use which should make creating that sexy file go quicker. The context file is the heart of Robotlegs and using the few methods I've written about here you can use it to make a fairly robust application linked together with dependency injection.
I've purposely left a lot out of this post. This is because I just want to wet your appetite to give it a shot as well. Also, I'd like to hear what kind of questions come up for you in the comments. Finally, I could write a lot more just about the context class and favoring configuration over convention( well sort of ), but it would just turn into a mess of words and I'd be surprised if you read this far anyway. If you did, thank you. I'd love to hear what you think of Robotlegs if you've tried it out or even if you've decided not to.
Flash Friday - AS3 Signals Basics
A short while back I mentioned a couple new open source projects I started working with at my new job. One of those projects was AS3 Signals. Since I've begun using it I've really grown to like it and I wanted to explain why. Hopefully my explanation of why will also include enough of the how. First off, have been a big fan of the AS3 event model since it came out with flash player 9. It, like many other AS3 updates, was much cleaner than the ways we were doing things in AS1/2. However, there have always been a few things that have bugged me just a little about the native event model.
I have to look at documentation to see what events a class object fires.
I can't count the number of times I am looking into a new framework, or even native classes, and I hope it fires an event but I can't just tell by code completion alone. Worse yet, sometimes important events don't even get documented so I have to search through source code to see what gets dispatched. On the flip side, if I'm writing custom classes I don't like writing documentation. I like my code to be readable like a good book, if at all possible. The AS3 event model forces you to read and write documentation. How could AS3 Signals clear up this problem though?
AS3 Signals clears up the problem of needing the documentation by having you create individual signals as objects in a class. This allows the programmer the opportunity to name the signal appropriately, thus making it easy to understand for the user of this class. Thus eliminating the requirement for documentation.
Let's give a simple example. Let's say you have a class that loads an external file and isn't ready until that file is loaded and parsed. With AS3 Signals this is a relatively simple process.
First create the signal in the class:
public var becameReady:Signal; public function MyFileLoader( url:String ):void{ becameReady = new Signal(); // you can come up with your own code here. }
Now anyone wanting to use the MyFileLoader class can see that you have a signal called becameReady. Hopefully they can tell from just that info what it does. Or perhaps you can come up with better naming. Either way this is an improvement.
Event types are strings
Strings are flexible and easy to read ( such as in a trace or error message ). The other problem is that they are not type safe and I've had times where event type naming collisions do happen. AS3 signals takes care of this problem by both solving and circumventing the problem.
AS3 Signals circumvents the problem by having you create separate ISignal objects for each type of event you would have dispatched in the past. Even though they are all of type ISignal, they are each distinct fields on an object. For example, if I had a class controlling a form, some of its signals might look like this:
public var submitClick:NativeSignal; public var clearClick:NativeSignal; public var completed:Signal;
AS3 also solves the problem by having event type checking, if you are working with the native event model. I haven't worked much with this at this point so I won't get into this in this article. If you'd like to know more about this comment below and I can write about it in a future article.
Custom events and event dispatcher classes take too much code for the simplest task
We've all been there, we want to make a custom events for a project but we have to write a whole new class to encapsulate what we need. Also, if we want to dispatch these events from a class that doesn't extend EventDispatcher we need to make sure to implement IEventDispatcher. Sure, these are relatively simple tasks but they take time and you are writing code that reeks of duplication.
As you have seen above, it is really simple to create a "custom" signal. Just define and initialize a new signal. Dispatching it is just as easy.
public var somethingHappened:Signal; private function init():void { somethingHappened = new Signal(); } private function doSomething():void { // custom code that does something ;) somethingHappened.dispatch(); }
Too make the signal more custom you can send as many objects as you want in the dispatch call. I'll leave that as an exercise for the reader ( or you can exercise the comments section and I'll show you what I mean below ).
If you just want to listen once you have to write extra code
The native event model doesn't make it easy to listen once. Perhaps you want to listen to a view's close button for just one click. With the native event model you have to remember to call removeEventListener in you event handler or else your program may not work as expected and it will likely create a nasty memory leak. AS3 Signals simplifies the process with the addOnce() call.
private function init():void { doSomething(); view.closeButtonClick.addOnce( onCloseButtonClick ); } private function onCloseButtonClick(){ view.close(); }
The previous addOnce call was so minor you might not have noticed it in the code. Really, that's all it takes. Signals are really quite easy to clean up.
Cleaning up listeners is difficult
When trying to find memory leaks, the first thing I look for is calls to addEventListener. They are usually the major culprit because it is so easy to lose track of which listeners were added to an object and for which event type. As you saw above, Signal objects have a built in mechanism for removing listeners after a single call if you want. They also have a simple way to remove all listeners from themselves, the aptly named removeAll function.
function close():void { closeButtonClick.removeAll(); otherSignal.removeAll(); }
Conclusion
This article was much longer than I thought it would be. If you made it this far, thank you for reading. I hope you see how AS3 Signals is an improvement over the native event model. Once you start using Signals you'll likely find yourself using events less and less. The event model is still core to AS3 though so there are some good ways to use them together. I plan to write a ( hopefully shorter ) article on using AS3 Signals with the native event model in the future. If you have any questions, comments or requests regarding AS3 Signals please let me know in the comments below.
Testing if an object is in a set
One useful operator I've found when writing MySQL queries is the "IN" operator. The elegance of the simple statement to see if a value is equal to any item in a set is something I've alway wanted to have at my fingertip while writing much of the code I do in AS3. At some point I got tired of using something akin to as3corelib's ArrayUtils.arrayContainsValue function as I wanted to see if I could find a better solution for more readable code.
AS3's "in" operator
My first stop was AS3's "in" operator. At first it seemed like it might work and the code would look like the following:
value in [apple,banana,kiwi,orange]
Unfortunately, the previous line would only resolve to true if value was equal to 0,1,2 or 3. The in
operator only checks against the indexes of an array ( or the fields in an object ). So unfortunately it wouldn't work for my needs. It looks like I was going to have to roll my own and I wanted to see if I could create something that read like the following:
anyObject.isIn( ... args )
Actionscript is [still] a prototype language
Back in the days of AS1 and AS2 you could easily add functionality by adding to a class's prototype chain. If you wanted to add functionality to everything, all you would have to do is add to the Object
class prototype. The good news, is that this is still possible in AS3. The [not quite] bad news is that due to strong type checking you can't have a line like I wrote above without disabling strict type checking in the compiler. That's not something I'm willing to give up so I came up with something that could look like the line above but with strict type checking enabled it would look like the following:
anyObject[IS_IN]( ... args )
A little less readable than I would like but using the IS_IN
constant has a benefit of making it easy to import and use with Flex/Flash Builder. It also has the benefit of working with anything that extends objects which has some cool benefits. For instance you can write the following:
4[IS_IN]( 1, 2, 3, 4 ); // returns true
true[IS_IN]( true ); // returns true
true[IS_IN]( 1 ); // returns false
"foo"[IS_IN]( "foo", "bar" ); // returns true
If this sounds like something you might like to use feel free to download the file. I've also included my flexUnit4 test class which will show you more of how this can be used.
EDIT: There are some problems with this file as it was originally created as a proof of concept. For educational purposes I am keeping the original file up here and you can learn about the changes and why I made them at: http://ducharme.cc/flash-friday-is-in-refactored/
Embedding Fonts in Flex Builder Using the Flash IDE
[ad#Adobe Banner] Flex is great for building rich internet applications quickly. Building an application quickly is nice, but to give your application that truly professional touch you need to customize the look and feel of your app. In order to fully customize the look and the feel you will need to use a font that's different than the default serif font that is used everywhere.
The flash player affords you the opportunity to embed many non standard fonts into your app, something that sets it apart from AJAX applications that need to rely on web safe fonts. In the flash IDE this is as easy as setting the font in the properties panel and selecting which character from that font which you want to embed. In a Flex app, things get a little trickier - especially if you want to use a non True Type font, which is the only type it can import natively. However, if you have the Flash IDE you can use its simplicity to get any font you can use in Flash into your Flex app.
The process is broken up into two steps.
- Create a SWF with the font(s) you need embedded in it
- Add Style (CSS) info to your Flex project that imports the font into your Flex project
Step one starts with the simplest of FLA files and can be created with earlier versions of the Flash IDE (so you can use Flash 8 or MX2004 if that's all you have). I recommend using a separate FLA for each font you want to embed, that way it is easier to catalog, store and reuse in other projects. Create 4 dynamic text fields. Each text field is for the different versions of the font so you should have:
- normal
- italic
- bold
- bold italic
You need to make sure you set up all 4 text fields to embed all the glyphs from the font you will need. For most western languages Numerals, Punctuation and Basic Latin should cover all the glyphs you will need. Once again, make sure to set up the character embedding for all 4 text fields. If you notice certain parts of your flex document using the default font you may not have set up character embedding. You can of course leave out any of the 4 ( ie italic and italic bold ) that you aren't going to use but if you are going to reuse the SWF I would do all 4.
Once you are done setting the character embedding for all 4 text fields, publish the file to a SWF. [ad#Google Adsense] The second step of this process is to add Style to your Flex project that imports the font into the project. That's as simple as adding an @font-face entry to your CSS file or <mx:Style> block. At first you simply give it the path to your font SWF and the name of the font ( ie Futura Book, Calibri ).
@font-face
{
src:url( "path/to/yourFont.swf" );
fontFamily:"Exact Name of Font"
}
You also need to add an @font-face entry for each version of the font you want to use. So if you also wanted to use the bold version you would add the following:
@font-face
{
src: url( "path/to/yourFont.swf");
fontWeight:"bold";
fontFamily:"Exact Name of Font";
}
After you are done adding the appropriate @font-face entries you can style any component you need to or you can style the entire application with your font.
Application
{
fontFamily:"Exact Name of Font";
}
There are a couple other ways to embed fonts, and if you don't have a version of the flash IDE those are the only way to go. If there is enough interest I can cover those in comments or another post. However this is by far the simplest, it allows you the ability to embed non True Type fonts and you can reuse a font more quickly in the future. [ad#Adobe Banner] If you liked this post please subscribe to my RSS feed and/or follow me on Twitter. If you only want to see my Flash Friday posts you can follow the subscribe to the Flash Friday feed. How's that for alliteration :) Until next time keep on coding.
Other Posts
Many of my programming posts are Flex or Actionscript related and will now be posted in the FlexCoders group. So I haven't stopped posting about programming, just moved where much of it occurs.
Yahoo Flex Map Component Part 3 available
Part 3 in my multi part series on building a flex component out of the Yahoo! Maps API is available over at the Flexcoders group.
In part 1 of this series I talked about the reasons why you would want to make a flex component out of something you can do in actionscript. In part 2 I discussed the basics of the component architecture. From that second article you can create a component that works however you still haven't handled most of the reasons to make a component in the first place. In this article I will take care of those issues the issues of data binding, event handling and making it easier for non coders( sometimes called designers or managers :) ) to work with.
YahooFlexMap part 2 is available
Part 2 in my multipart series about creating a Flex component fromt he new Yahoo! map API for actionscript 3 is now available in the my.opera Flexcoders group blog.
In part 1 of my series on making a flex component out of the new Yahoo! Maps API for actionscript 3 I talked about the reasons I was taking the time to componentize something I could easily build with pure actionscript. Today I will be talking through the basics of creating a visual component. While these basics are covered at the LiveDocs for Flex 3, I will go over them in a slightly different way, as well as talk about how they affect the Yahoo! map component in particular.
Also make sure to join the Flexcoders group as it is new and looking for new members. At the very least, feel free to ask questions in the forum.