how do I indicate an unset default parameter of type Number in Flex3? - actionscript-3

for String and Object type, I can set the default parameter to null to indicate that it was not set by the caller. Is there a mechanism in flex3 to do the same for the Number type?
So for instance:
public function myMethod( stringVar:String=null, ObjectVar:Object=null, numberVar:Number )
{
...
}
I could do the following, but it just feels ugly
public function myMethod( numberVarObj:Object=null )
{
var numberVarSet:Boolean=true;
if( numberVarObj == null ) {
numberVarSet = false;
}
and then everywhere I want to use numberVar I can check for numberVarSet and cast as a Number.

I suppose you could always try:
var numberVar:* = null;
And then set it to a number when you want . . . It would be nice to have a solution that is strongly typed though.
Another option, as specified in Adobe's Docs (scroll down to default values), would be to treat the value NaN as null. However, if your data has ANY chance of containing a NaN value, this is a horrible idea.

I'd recommend the "ugly" solution you have, but if you really want another option you can use NaN and then use isNaN(num) to check the value.

Related

Return true when query gives 1

I want to save a true/false in my MySQL database. I'm saving 1/0 in an INT column to do this. When I select it, I get the 1 or 0, but I want it to return true/false to my PHP code, without having to rewrite the database.
Can I use another column type? Should I save it differently?
Update: My question is about not wanting to rewrite the returned value. I'm getting a lot of results from my database. Many of those are true/false, but some are 0s because the price is 0, so I don't want to universally rewrite all 1s and 0s. I also don't want to manually rewrite 10 columns.
To follow up my comment, here's a more detailed response which also covers the PHP side, although this probably belongs on StackOverflow.
I've always just used tinyint, although you can use bool/boolean which are synonyms for tinyint(1)
However as of MySQL 5.0.3 you can use the bit type:
As of MySQL 5.0.3, the BIT data type is used to store bit-field values. A type of BIT(M) enables storage of M-bit values. M can range from 1 to 64.
Next, assuming you have an active column, perhaps to store if a user is active, you could use PHP's automatic type conversion to handle this quite simply.
// Obviously you'd replace this with your database call
$results = [['active' => 1], ['active' => 0]];
foreach($results as $row) {
if ($row['active'] == true) {
echo "true\n";
}
else {
echo "false\n";
}
}
You don't strictly need to do anything.
PHP does not, and can not, use strongly typed variables. So, if you receive an (int) 1 from your query results, you can simply use this 1 as a boolean without rewriting or changing anything.
$intOne = (int) 1; //explicitly treat the variable as an integer
var_dump((bool) $intOne); //treat the variable as a boolean
When used in any boolean context, like if ($variable)... then any of these types will be considered to be false by PHP:
the boolean FALSE itself
the integer 0 (zero)
the float 0.0 (zero)
the empty string, and the string "0"
an array with zero elements
an object with zero member variables (PHP 4 only)
the special type NULL (including unset variables)
SimpleXML objects created from empty tags
... And, most importantly;
Every other value is considered TRUE (including any resource).
Source: PHP Manual > Booleans (english)
So while you can change the storage type of your column in mysql, this won't really change the way PHP handles the variable retrieved from your results at all.
Historically, I've always used a column of type TINYINT(1) to store boolean values in mysql, and as Tom Green points out, recent mysql versions provide a new BIT type, which might be appropriate. To the best of my knowledge, mysql does not currently have an actual boolean data type.
You could just as easily use a column of type VARCHAR(1), though, because PHP can and will use any value as a boolean, thanks to the glorious, majestic, and sometimes maddening, PHP Type Juggling.
If you're trying to use the values you're retrieving for boolean logic, just use the values you receive from mysql like booleans and it will work:
if ($valueFromResults) {
//The value was something like true
} else {
//The value was something like false
}
If you're trying to actually echo out the words "true" and "false", then you're probably best served by explicitly echoing the words out yourself, like this;
if ($valueFromResults) {
echo "true";
} else {
echo "false";
}
or, in my preferred shorthand;
echo ($valueFromResults) ? "true" : "false" ;
Update You mentioned in a comment that you want to pass the values through json_encode() and use them in javascript.
JavaScript treats any real value, like int 1, as true and any empty value, like int 0, or an empty string, as false. So if your json_encode() output gets used in actual JavaScript, the int values will still work as boolean values. So the integer values from your database should still work as they are.
Just check that your integer results are encoded as integers by PHP and not as strings - they should be encoded correctly by default - because "0" == true in javascript, but 0 == false.
For a boolean value (true/false), you should use the mySql type bit or tinyint(1).
$boolean = $mysql_data ? true : false;

Best way to cache results of method with multiple parameters - Object as key in Dictionary?

At the beginning of a method I want to check if the method is called with these exact parameters before, and if so, return the result that was returned back then.
At first, with one parameter, I used a Dictionary, but now I need to check 3 parameters (a String, an Object and a boolean).
I tried making a custom Object like so:
var cacheKey:Object = { identifier:identifier, type:type, someBoolean:someBoolean };
//if key already exists, return it (not working)
if (resultCache[cacheKey]) return resultCache[cacheKey];
//else: create result ...
//and save it in the cache
resultCache[cacheKey] = result;
But this doesn't work, because the seccond time the function is called, the new cacheKey is not the same object as the first, even though it's properties are the same.
So my question is: is there a datatype that will check the properties of the object used as key for a matching key?
And what else is my best option? Create a cache for the keys as well? :/
Note there are two aspects to the technical solution: equality comparison and indexing.
The Cliff Notes version:
It's easy to do custom equality comparison
In order to perform indexing, you need to know more than whether one object is equal to another -- you need to know which is object is "bigger" than the other.
If all of your properties are primitives you should squash them into a single string and use an Object to keep track of them (NOT a Dictionary).
If you need to compare some of the individual properties for reference equality you're going to have a write a function to determine which set of properties is bigger than the other, and then make your own collection class that uses the output of the comparison function to implement its own a binary search tree based indexing.
If the number of unique sets of arguments is in the several hundreds or less AND you do need reference comparison for your Object argument, just use an Array and the some method to do a naive comparison to all cached keys. Only you know how expensive your actual method is, so it's up to you to decide what lookup cost (which depends on the number of unique arguments provided to the function) is acceptable.
Equality comparison
To address equality comparison it is easy enough to write some code to compare objects for the values of their properties, rather than for reference equality. The following function enforces strict set comparison, so that both objects must contain exactly the same properties (no additional properties on either object allowed) with the same values:
public static propsEqual(obj1:Object, obj2:Object):Boolean {
for(key1:* in obj1) {
if(obj2[key1] === undefined)
return false;
if(obj2[key1] != obj2[key1])
return false;
}
for(key2:* in obj2)
if(obj1[key2] === undefined)
return false;
return true;
}
You could speed it up by eliminating the second for loop with the tradeoff that {A:1, B:2} will be deemed equal to {A:1, B:2, C:'An extra property'}.
Indexing
The problem with this in your case is that you lose the indexing that a Dictionary provides for reference equality or that an Object provides for string keys. You would have to compare each new set of function arguments to the entire list of previously seen arguments, such as using Array.some. I use the field currentArgs and the method to avoid generating a new closure every time.
private var cachedArgs:Array = [];
private var currentArgs:Object;
function yourMethod(stringArg:String, objArg:Object, boolArg:Boolean):* {
currentArgs = { stringArg:stringArg, objArg:objArg, boolArg:boolArg };
var iveSeenThisBefore:Boolean = cachedArgs.some(compareToCurrent);
if(!iveSeenThisBefore)
cachedArgs.push(currentArgs);
}
function compareToCurrent(obj:Object):Boolean {
return someUtil.propsEqual(obj, currentArgs);
}
This means comparison will be O(n) time, where n is the ever increasing number of unique sets of function arguments.
If all the arguments to your function are primitive, see the very similar question In AS3, where do you draw the line between Dictionary and ArrayCollection?. The title doesn't sound very similar but the solution in the accepted answer (yes I wrote it) addresses the exact same techinical issue -- using multiple primitive values as a single compound key. The basic gist in your case would be:
private var cachedArgs:Object = {};
function yourMethod(stringArg:String, objArg:Object, boolArg:Boolean):* {
var argKey:String = stringArg + objArg.toString() + (boolArg ? 'T' : 'F');
if(cachedArgs[argKey] === undefined)
cachedArgs[argKey] = _yourMethod(stringArg, objArg, boolArg);
return cachedArgs[argKey];
}
private function _yourMethod(stringArg:String, objArg:Object, boolArg:Boolean):* {
// Do stuff
return something;
}
If you really need to determine which reference is "bigger" than another (as the Dictionary does internally) you're going to have to wade into some ugly stuff, since Adobe has not yet provided any API to retrieve the "value" / "address" of a reference. The best thing I've found so far is this interesting hack: How can I get an instance's "memory location" in ActionScript?. Without doing a bunch of performance tests I don't know if using this hack to compare references will kill the advantages gained by binary search tree indexnig. Naturally it would depend on the number of keys.

PHP force a var to have a certain type

This may be a stupid question but I might aswell as it :)
is there away to force
$tel1 = '05';// string
settype($tel1,'string');
$tel1 = 06;//either throw error, or convert it to string automatically.
var_dump($tel1);//(string [2]) 05
The above code is of the top of my head so might not be accurate but I need to keep a variable as a string not numeric, because of some silly thing I have done, now my phone numbers lose the leading 0s :-(
n I cn't rewrite it because it will mess up with other numeric types,b4 u ask it was an automated service for db to check if it was a numeric value or not,
UPDATE
This is the problem
function escape($str){
if(is_numeric($str)){
return $str;
}else{
return "'".mysql_real_escape_string($str).'\'';
}
}
$tel1 = "06";
$sql = 'SELECT * FROM blabla WHERE id = '.escape($tel1).'';
//above is same as below
$sql = 'SELECT * FROM blabla WHERE id = 06 ';
I can't change anything inside the scape function because other inputes thruout the website are using this function, I dont wanna mess their validations.
Your use of is_numeric tests for numeric content, not an integer type. But then you take a variable called $str which implies you want it to be a string.
Perhaps use:
function escape($val) {
if (is_numeric($val) && !is_string($val)) {
return $val;
}
else{
return "'" . mysql_real_escape_string($val) . '\'';
}
}
Now strings will be escaped and quoted, but not if they contain only numeric content.
you can do something like:
$string = (string) $int;
or use a function
$string = strval($int);
You can't force a variable to a specific type in the global scope.
You can force Arrays and Objects in a function.
function getElementsByClassName(DOMNode $parentElement, Array $classNames) {
...
}
If you pass an object that is not an instantiation of DOMNode (or a subclass), or if you don't pass an Array as the second argument, you'll get an error.
You can of course cast any variable, e.g. (string) $tel1.
You shouldn't be treating phone numbers as Ints anyway, because of leading zeroes and possible parenthesis and dashes. Also, once your telephone number is an Int, it won't know its 0 padding anymore because it will be discarded, so casting it back won't give you the original String.
To cast a variable you can use something like:
$i = 1;
$s = (string) $i;
Depending on the db adaptor you might not be able to detect the type being returned from the database. I believe it's PDO that returns everything (even INT values) as strings.
The number_format() function may be of use to you too.
If you declare a variable as:
$var = 06;
it immediately becomes 6 without leading zero because leading zero when it comes to integers is meaningless and therefore it's cut out.
In other words, your variable has to be created as string, which is what you probably deduced yourself.
Quick fix would be the following: you can add another parameter to your escape() function.
For example:
function escape($str, $force_str = false)
{
if($force_str)
{
// do your conversion, the rest of the site will by default pass false so nothing will be broken
}
}
As alex said, start by making sure the phone number is never converted from string to int in your own code. Then, you need to make sure it will not be converted when sent to your SQL DB.
It ought to work if you do it this way:
$sql = "SELECT * FROM blabla WHERE id = '" . mysql_real_escape_string($tel1) . "'";
This is the same as
$sql = "SELECT * FROM blabla WHERE id = '06'";

Grails: can I make a validator apply to create only (not update/edit)

I have a domain class that needs to have a date after the day it is created in one of its fields.
class myClass {
Date startDate
String iAmGonnaChangeThisInSeveralDays
static constraints = {
iAmGonnaChangeThisInSeveralDays(nullable:true)
startDate(validator:{
def now = new Date()
def roundedDay = DateUtils.round(now, Calendar.DATE)
def checkAgainst
if(roundedDay>now){
Calendar cal = Calendar.getInstance();
cal.setTime(roundedDay);
cal.add(Calendar.DAY_OF_YEAR, -1); // <--
checkAgainst = cal.getTime();
}
else checkAgainst = roundedDay
return (it >= checkAgainst)
})
}
}
So several days later when I change only the string and call save the save fails because the validator is rechecking the date and it is now in the past. Can I set the validator to fire only on create, or is there some way I can change it to detect if we are creating or editing/updating?
#Rob H
I am not entirely sure how to use your answer. I have the following code causing this error:
myInstance.iAmGonnaChangeThisInSeveralDays = "nachos"
myInstance.save()
if(myInstance.hasErrors()){
println "This keeps happening because of the stupid date problem"
}
You can check if the id is set as an indicator of whether it's a new non-persistent instance or an existing persistent instance:
startDate(validator:{ date, obj ->
if (obj.id) {
// don't check existing instances
return
}
def now = new Date()
...
}
One option might be to specify which properties you want to be validated. From the documentation:
The validate method accepts an
optional List argument which may
contain the names of the properties
that should be validated. When a List
is passed to the validate method, only
the properties defined in the List
will be validated.
Example:
// when saving for the first time:
myInstance.startDate = new Date()
if(myInstance.validate() && myInstance.save()) { ... }
// when updating later
myInstance.iAmGonnaChangeThisInSeveralDays = 'New Value'
myInstance.validate(['iAmGonnaChangeThisInSeveralDays'])
if(myInstance.hasErrors() || !myInstance.save(validate: false)) {
// handle errors
} else {
// handle success
}
This feels a bit hacky, since you're bypassing some built-in Grails goodness. You'll want to be cautious that you aren't bypassing any necessary validation on the domain that would normally happen if you were to just call save(). I'd be interested in seeing others' solutions if there are more elegant ones.
Note: I really don't recommend using save(validate: false) if you can avoid it. It's bound to cause some unforeseen negative consequence down the road unless you're very careful about how you use it. If you can find an alternative, by all means use it instead.

Why can't typed optional arguments have a default of Null?

In ActionScript 3, when you declare an optional argument by giving it a default value, the value null cannot be used on typed arguments.
function Action(Param:int=null){
// 1184: Incompatible default value of type Null where int is expected.
}
function Action(Param:int=0){
// No compiler errors
}
Any workarounds for this, or general purpose values that can apply to all data types?
You can change your int to Number and then can set it to NaN which is a special number that means 'not a number' and this can represent your null state for a Number.
To check if something is NaN, you must use the isNaN() function and not val == NaN, or you will not get what you expect.
function Action(param:Number = NaN) : void {
trace(param);
}
For all other objects, you can set them to null, but 'primitive' numbers are handled differently in Actionscript.
int variables cannot be null, that's why you get that error, only reference types like objects can be null
Instead you can use NaN as a special number instead of null. If you want to check if something is NaN you mus use the isNaN function.
you could also include a flag in the method signature to avoid having the parameter promoted from int to number:
function whatever(intProvided:Boolean = false, someInt:int = 0):void
{
if(intProvided)
doSomeStuff();
}