Default value for function argument, guaranteed to be unique - actionscript-3

Just wondering, if i could provide default argument for function in ActionScript 3 which is never can be passed to the function by user. This is the case:
public function getAttr (obj:Object, key:String, def:* = DEFAULT_VALUE):* {
if (!obj.hasOwnProperty(key)) {
if (def === DEFAULT_VALUE) {
throw ReferenceError('Attribute not found: ' + key);
} else {
return def;
}
} else {
return obj[key];
}
}
I cannot use as DEFAULT_VALUE any of null, undefined, Number, Boolean or String here, cause, logically, user could use any of this values. I need something really unique here. In python, for example, i can do this:
_DEFAULT_VALUE = object()
def get_attr(obj, key, d=_DEFAULT_VALUE):
if not hasattr(obj, key):
if d is DEFAULT_VALUE:
raise KeyError('Attribute not found: {}'.format(key))
else:
return d
else:
return obj[d]
But in ActionScript 3 such approach produces an error:
Error code: 1047: Parameter initializer unknown or is not a compile-time constant.
Maybe some hack here?

Your problem here is that def value have to be a compile time constant so there is no way to store a default value into a var and pass it as a default value.
But what you really want here is to know if the user have passed an extra parameter into the def field of the function, so you can check the arguments array length and see if there is 2 or 3 parameters passed.
public function getAttr (obj:Object, key:String, def:* = null):* {
if (!obj.hasOwnProperty(key)) {
if (arguments.length==2) { // no default value passed to the function
throw new ReferenceError('Attribute not found: ' + key);
} else {
return def;
}
} else {
return obj[key];
}
}

Transfer null, and check for null. After all, null is a default value that's really nothing, if you require a parameter to be supplied and be valid, use null as default value so that if something will be supplied, it will not be null, thus valid.

Vesper's answer seems correct for your situation. But, I've used similar method for singletons though:
class Singleton
{
private var k_CONS_BLOCKER:Object = {};
public Singleton(cons_blocker:Object)
{
if(cons_blocker!=k_CONS_BLOCKER)
{
throw new Error("Use static getter to get the object");
}
}
public function getObject():Singleton
{
return obj;//you can of course create it now or do some other logic...
}
}
I know the answer isn't directly related to the question, but I think the idea solves the problem in general.
HTH.

Related

Actually there was zero interactions with this mock error?

I am trying to write test case but stuck with this error. How to fix this error ?
#Override
public boolean isDuplicateSystemDetail(SystemFormBean systemFormBean){
List<BrmSystem> list = systemDao.isDuplicateSystemDetail(systemFormBean);
if(CollectionUtils.isNotEmpty(list)){
return true;
}else{
return false;
}
}
---------------------------------------------------------------------------
#Test
public void isDuplicateSystemDetail_Should_Return_True(){
List<BrmSystem> list = new ArrayList<BrmSystem>();
BrmSystem brmSystem = new BrmSystem();
SystemFormBean systemFormBean = new SystemFormBean();
brmSystem.setSystemName("Test");
list.add(brmSystem);
when(systemDao.isDuplicateSystemDetail(systemFormBean)).thenReturn(list);
}
Probably SystemFormBean class doesn't override equals(). So when isDuplicateSystemDetail(systemFormBean) invokes, it has another object of this class as a parameter which is not the same as the one you've created manually (by default Object.equals() compares memory adresses which would be false in your case).
Try to override equals() to compare by f.e. actual fields of SystemFormBean or rewrite "when" clause as
systemDao.isDuplicateSystemDetail(Mockito.any(SystemFormBean.class))

in defining a function in Dart, how to set an argument's default to { }, ie, an empty Map?

love how Dart treats function arguments, but cannot accomplish what should be a simple task:
void func( String arg1, [ Map args = {} ] ) {
...
}
get the error
expression is not a valid compile-time constant
have tried new Map() for example, with same error.
You have to use the const keyword :
void func( String arg1, [ Map args = const {} ] ) {
...
}
Warning : if you try to modify the default args you will get :
Unsupported operation: Cannot set value in unmodifiable Map
The default value must be a compile time constant, so 'const {}' will keep the compiler happy, but possibly not your function.
If you want a new modifiable map for each call, you can't use a default value on the function parameter. That same value is used for every call to the function, so you can't get a new value for each call that way.
To create a new object each time the function is called, you have to do it in the function itself. The typical way is:
void func(String arg1, [Map args]) {
if (args == null) args = {};
...
}

p:autocomplete with POJO - how to get null value?

I have a simple problem. I suggest a list of objects to the user to choose from using p:autocomplete. At the same time the user can create new objects 'on the fly' by typing names that are not in the suggestion. The whole setup is very similar to the vanilla POJO showcase, but I'm posting the code here:
<p:autoComplete id="player" value="#{entry.player}"
completeMethod="{abean.complete}"
var="s1" itemLabel="#{s1.name}" itemValue="#{s1}"
converter="PlayerConverter">
<p:ajax event="itemSelect" listener="#{abean.playerSelected}"/>
</p:autoComplete>
The converter:
#FacesConverter(forClass=Player.class, value = "PlayerConverter")
public class PlayerConverter implements Converter
{
#Override
public Object getAsObject(FacesContext ctx, UIComponent cmp, String value)
{
Player player = null;
if ( !(value==null || value.trim().isEmpty()))
{
// Autocomplete did find a match, the appropriate
// player is returned
try
{
Integer id = Integer.valueOf(value);
player = TeamService.getInstance().getPlayer(id);
}
catch (NumberFormatException e)
{
// Autocomplete found no match, the entered String
// is given. Create an ad-hoc player as response
player = new Player();
player.setName(value);
player.setAdHoc(true);
}
}
return player;
}
#Override
public String getAsString(FacesContext ctx, UIComponent cmp, Object value)
{
String result = null;
if (value instanceof String)
{
result = (String) value;
}
else if (value instanceof Spieler)
{
Integer id = ((Spieler)value).getId();
result = (id == null) ? null : id.toString();
}
return result;
}
}
The problem I am facing seems simple: how do I coerce this construction into allowing the user to simply erase a value? When the user deletes the content of the input field, I would expect to get a call to PlayerConverter with a null or empty value, but that doesn't happen.
How do I get my hands on empty input?
I found a workaround. Use a converter and add a flag to the objects you are displaying in the p:autocomplete. Set the flag to 'false' in the converter's getAsString method. Set it to 'true' in the converter's getAsObject method. The latter is not called when the user emptied the autocomplete field. Therefore the flag remains 'false'. And that you can check in the action method of your command button.
I hope it helps someone.

How can I define a boolean function argument to be optional?

In ActionScript 3, is there a clean way to define a function that accepts an optional boolean argument ? As you may know, this is invalid :
public function test(param:Boolean = null):void {
trace(param);
}
This triggers the following error: VerifyError: Error #1102: Illegal default value for type Boolean. Since, Boolean is a primitive, I guess it makes sense that it cannot be set to null. The only workaround I found is to cast the parameter to an object :
public function test(param:Object = null):void {
trace(Boolean(param));
}
However, this does not feel very clean, particularly if you are developing libraries. ASDoc will generate API documentation that says the expected parameter is an Object whereas what is really needed is a Boolean.
Is there a better approach ?
When you say optional, I assume that you mean if there isn't a value supplied then something different should happen compared to if you had a default value of true or false.
You could make your own object to handle the three states that you need and maintain code readability by using a class like this:
public class Condition
{
private var _value:* = null;
public function Condition(initial:* = null)
{
value = initial;
}
public function set value(n:*):void
{
if(_value === null || _value === false || _value === true)
{
_value = n;
}
}
public function get value():*{ return _value; }
}
And then your function could be:
function test(param:Condition = null):void
{
if(param && param.value != null)
{
trace(param.value);
}
}
test( new Condition() );
test( new Condition(true) );
As you said Boolean can not be set to null value.
Therefore, you should specify a default value that is either true or false.
public function test(param:Boolean = false):void {
trace(param);
}
But because you need the third case where nothing is set, one option could be to accept any Object but throw an exception if it is not null and not a boolean:
public function test(param:* = null):void
{
if (param != null)
{
if ((param == true) || (param == false))
{
trace(Boolean(param).toString());
}
else
{
throw new CustomError("param should be a boolean");
}
}
else
{
// Do nothing
}
}
Note that this solution also accept objects or primitives that can be compared to true or false such as 0, 1, or [].
From the good suggestions and discussion above I think that, in a library scenario and for simplicity's sake, the best way remains to type the parameter as Object with a default value of null but to request a Boolean in the API documentation :
/**
* #param param Boolean object or null
*/
public function test(param:Object = null):void {
trace(Boolean(param));
}
This allow the user of the library to pass a either a Boolean or nothing at all. Thanks everyone.
There was a tonne of discussion on my previous answer, but this is the correct way to have a function that accepts one of three states. My previous answer attempted to retain the use of a Boolean value like you were requesting, but that is not the right way to go about it.
Create a class that defines three values:
class State
{
public static const EMPTY:int = -1;
public static const FALSE:int = 0;
public static const TRUE:int = 1;
}
Your function will accept an int (the type of each of the three properties within your State class). It will deal with the three possible values. You can use concise commenting to notify the developer of what thee values the function is expecting, referencing the State class. The default value can be -1 aka State.EMPTY.
/**
* Function description.
* #param state One of three states, defined by State.
*/
function test(state:int = -1):void
{
switch(state)
{
case State.EMPTY:
// No value given.
break;
case State.TRUE:
// True.
//
break;
case State.FALSE:
// False.
//
break;
default:
throw new ArgumentError("Unsupported value for test()");
break;
}
}

Best practice for interface with a getter function that could return multiple types

I have several data manipulation widgets that all implement a custom IPropertyEditor interface. I would like to include a GetValue getter, but the return types could be String, Boolean or int, off the top of my head. In AS3, all of that inherits from Object, so I could have GetValue return an object, but I don't feel great about that approach. At the risk of asking a subjective question, does anyone have any recommendations on how to approach this?
In ActionScript I'm pretty sure you can set a variable return type by defining a function in the following way:
public function getValue():* {
return "Any of these would be fine.";
return true;
return 1;
return new Sprite();
}
Hope that helps.
In practice, there is an actual getter/setter model in ActionScript. For your case, you could use it like this:
private var _value:*;
public function get value() : * {
return _value;
}
public function set value(val:*) : void {
if (typeof val == "int" || typeof val == "boolean" || typeof val == "string") {
_value = val;
}
}
This limits the user to setting (per your requirements) the value of this "value" property to data types int, Boolean, or String.