I see some java code does a cleaner way to exit as shown in this code.
if(a!=1) {System.exit();}
//If equal 1, execute the code below
Is there any similar keyword for Actionscript to stop a function (not exit a loop or application) as alternative to break keyword?
private function isInt():void {
if(a!=1) { /* stop executing the code after these */ }
b=a;
}
The Java code you quote exits the entire process - it stops executing. Flash runs inside a host process such as a web browser which should not be arbitrarily shut down - what if the user had content on other tabs?
If you specifically wanted to send a signal to the hosting browser, you should use fscommand or the newer mechanisms and let the browser/web page decide what to do.
If you just want to prevent any more execution of your function, just use 'return;' to leave the function you're in without doing any more processing.
Using a conditional return statement may seem clean and beautiful at first, but it can become a problem when refactoring, because it doesn't show its intent clearly.
What you are trying to say is this:
if my conditions are met, execute the next statement.
But what you are saying is:
if my conditions are not met, get out of here.
Example #1
Say you have a complex method with two or three nested if statements:
function myComplexMethod ( param1 : int, param2 : int, param3 : String ) : String {
var ret:String = null;
if (param3 != null) {
ret = param3;
if (param2 != 0) {
ret += param2;
if (param3 != 0) {
ret += param1 + param2;
}
}
}
return ret;
}
Example #2
Of course, the same method would look better using conditional return statements:
function myComplexMethod ( param1 : int, param2: int, param3:String ) : String {
if (!param3) return null;
var ret : String = null;
ret += param3;
if (param2 == 0) return ret;
ret += param2;
if (param1 == 0) return ret;
ret += param1 + param2;
return ret;
}
But at first glance, can you really tell what the output of this method is going to be?
Example #3
What if you were going to really clean up your code? If you refactored the code to reflect the intent of each block, the complex method would become a simple method:
function mySimpleMethod ( param1 : int, param2: int, param3:String ) : String {
return param3 != null ?
outputOfAllParams (param1, param2, param3 ) : null;
}
function outputOfAllParams ( param1 : int, param2: int, param3:String ) : String {
return param2 != 0 ?
param3 + combinedOutputOfIntParams ( param1, param2 ) : param3;
}
function combinedOutputOfIntParams ( param1 : int, param2: int ) : String {
return param1 != 0 ?
param2 + "" + sumOfIntParams( param1, param2) : "" + param2;
}
function sumOfIntParams( param1 : int, param2: int ) : int {
return param1 + param2;
}
In this last example, the code is easily readable, and you can see what it is supposed to do by just looking at it.
The thing is: You could easily use refactoring to get from example #1 to example #3 - it is obvious that each of the conditional blocks will be refactored to a new method. With the conditional return statements, it is far less intuitive: You'll have to check very carefully, where the desired code block ends, and when to return what.
Of course, if you're dealing with simple tasks like this, the benefits are not as obvious, but if you had real production code, you definitely want the intent as obvious as possible, and even if you were coming back to your own code in a couple of months, it would take you much longer to understand what it is supposed to do, if you used example #2.
Related
I am facing a problem where I have updated the namespace in my avsc schema file. Since we were using common processor created in Java to parse the XML to avro and were using the avsc file.
We have separated the interfaces and created 2 different namespaces and now having 2 avsc schemas which are identical just the namespace is different.
Since we have data which was generated using old namespace, I am unable to query this data with new data generated with new namespace.
Here is example of my schemas -
Old schema - "type" : "record",
"name" : "Message",
"namespace" : "com.myfirstavsc",
"fields" : [ {
"name" : "Header",.....**other fields**
New schema - "type" : "record",
"name" : "Message",
"namespace" : "com.mysecondavsc",
"fields" : [ {
"name" : "Header",.....**other fields**
When I query my hive table I get below exception
Failed with exception java.io.IOException:org.apache.avro.AvroTypeException: Found com.myfirstavsc.Property, expecting union
I am not sure how you are trying to read your data but use GenericDatumReader should solve your issue, after that you can convert the generic record to your specific records. I found something similar here
http://apache-avro.679487.n3.nabble.com/Deserialize-with-different-schema-td4032782.html
http://apache-avro.679487.n3.nabble.com/Deserialize-with-different-schema-td4032782.html
The link mentioned above is not work anymore, so add an explanation here.
We got the same error in a project named Hudi, so raised an issue about it: https://github.com/apache/hudi/issues/7284
After trouble shooting, the root cause of this exception org.apache.avro.AvroTypeException: Found hoodie.test_mor_tab.test_mor_tab_record.new_test_col.fixed, expecting union is Avro schema generator rule, it can't accept the change of namespace when handling UNION type.
According to Avro Schema Resolution doc, it can accept schema evolution if either schema is a union in reader or writer schema in GenericDatumReader(Schema writer, Schema reader). But it didn't mention there is another restriction about it: the full name of schema must be the same if the type is RECORD or ENUM or FIXED.
Code reference:
ResolvingGrammarGenerator#bestBranch
public class ResolvingGrammarGenerator extends ValidatingGrammarGenerator {
...
private int bestBranch(Schema r, Schema w, Map<LitS, Symbol> seen) throws IOException {
Schema.Type vt = w.getType();
// first scan for exact match
int j = 0;
int structureMatch = -1;
for (Schema b : r.getTypes()) {
if (vt == b.getType())
if (vt == Schema.Type.RECORD || vt == Schema.Type.ENUM ||
vt == Schema.Type.FIXED) {
String vname = w.getFullName();
String bname = b.getFullName();
// return immediately if the name matches exactly according to spec
if (vname != null && vname.equals(bname))
return j;
if (vt == Schema.Type.RECORD &&
!hasMatchError(resolveRecords(w, b, seen))) {
String vShortName = w.getName();
String bShortName = b.getName();
// use the first structure match or one where the name matches
if ((structureMatch < 0) ||
(vShortName != null && vShortName.equals(bShortName))) {
structureMatch = j;
}
}
} else
return j;
j++;
}
// if there is a record structure match, return it
if (structureMatch >= 0)
return structureMatch;
// then scan match via numeric promotion
j = 0;
for (Schema b : r.getTypes()) {
switch (vt) {
case INT:
switch (b.getType()) {
case LONG: case DOUBLE:
return j;
}
break;
case LONG:
case FLOAT:
switch (b.getType()) {
case DOUBLE:
return j;
}
break;
case STRING:
switch (b.getType()) {
case BYTES:
return j;
}
break;
case BYTES:
switch (b.getType()) {
case STRING:
return j;
}
break;
}
j++;
}
return -1;
}
...
}
I have this procedure
CREATE PROCEDURE dbo.spProcedure1
#intArray as dbo.intArray READONLY
AS
BEGIN
-- ...
END
which use user type as a parameter
CREATE TYPE dbo.IntArray AS TABLE (IntValue int NULL)
and I am calling the procedure from the C# ASP.NET MVC 4 project
// creating empty SQL #IntArray parameter
var emptyIntDataTable = new DataTable();
emptyIntDataTable.Columns.Add("IntValue");
// calling stored procedure
return Database.SqlQuery<int>(
#"spProcedure1 #p1",
new SqlParameter("p1", (object)Utils.ToDataTable(m.IntArray) ?? emptyIntDataTable)
).ToList();
// ToDataTable method which is returning null
public static DataTable ToDataTable<T>(this IList<T> data)
{
if (data == null)
return null;
... // code omitted because it is not working yet
}
the error which is throwed when calling stored procedure is
The table type parameter 'p1' must have a valid type name.
How to pass an empty table value?
Passing the list instead of datatable throw following error
var emptyIntDataTable = new List<int>;
No mapping exists from object type System.Collections.Generic.List`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] to a known managed provider native type.
In your code:
where it says:
return Database.SqlQuery<int>(
#"spProcedure1 #p1", new SqlParameter("p1",
(object)Utils.ToDataTable(m.IntArray) ?? emptyIntDataTable)
).ToList();
Change it to read:
return m.IntArray.Length > 0?
Database.SqlQuery<int>(#"spProcedure1 #p1",
new SqlParameter("p1",
(object)Utils.ToDataTable(m.IntArray))).ToList():
Database.SqlQuery<int>(#"spProcedure1")).ToList();
sample to show how to not pass table parameter
CREATE TYPE dbo.KeyIds]
AS TABLE(pkId int NOT NULL,
PRIMARY KEY CLUSTERED (pkId ASC)
WITH (IGNORE_DUP_KEY = OFF))
Go
-- ------------------------------
Create procedure testProc
#aIds dbo.keyIds readonly
as
Set NoCount On
if exists (select * from #aIds)
Select * from #aIds
else
Select 'No Aids passed in'
Go
-- ------------------------------
Exec dbo.testProc -- <--- Here I am NOT passing the #aids parameter
But, even though I am NOT passing the #aids parameter
it still works, and the subquery (select * from #aIds) still functions, and since it is an empty datatable the SP returns the empty message 'No Aids passed in'.
On the other hand, if you pass the parameter
Declare #MyIds dbo.keyIds
Insert #MyIds Values(1)
Insert #MyIds Values(2)
Insert #MyIds Values(3)
Insert #MyIds Values(4)
Insert #MyIds Values(5)
Exec dbo.testProc #MyIds -- <--- Here I AM passing the #aids parameter
it outputs the contents of the datatable parameter
C# code example...
public DataTable GetAccountTransactions(IEnumerable<int> accountIds)
{
const string procName = "FetchAccountTransactionData";
var acctIds = accountIds == null ?
new List<int>() : accountIds.ToList();
// -------------------------------------------------
var parms = DbParamList.Make();
// DbParamList is a List<IDbDataParameter>
// See here, ONLY ADD PARAMETER if list is NOT empty!
if (acctIds.Count > 0)
parms.AddSQLTableParm("aIds", acctIds);
try
{ // following constructs command obkect and calls SP
return Utilities.GetDataTable(schemaNm + "." +
procName, parms, copConn);
}
catch (SqlException dbX)
{
// Exception stuff
}
}
public class DbParamSortedList : SortedList<string,IDbDataParameter> { }
The alternative solution
prepare method for converting List<int> into dbo.IntArray type
public static DataTable IntArrayToDataTable(IEnumerable<int> ids)
{
if (ids == null)
return null;
DataTable table = new DataTable();
// datatable columns has to have same name as database type !
table.Columns.Add("IntValue", typeof(int));
foreach (int id in ids)
{
table.Rows.Add(id);
}
return table;
}
run sql stored procedure
var sqlParameters = new List<object>();
var parameter1 = Utils.IntArrayToDataTable(m.IntArray);
if (parameter1 != null)
sqlParameters.Add(new SqlParameter("intArray", parameter1)
// these variables are the key, without them it is not working
{
SqlDbType = SqlDbType.Structured,
TypeName = "dbo.IntArray"
});
else // parameter cannot be omitted !! even if all parameters are named !! otherwise parameter mismatch happens (in case of multiple parameters)
sqlParameters.Add(new SqlParameter("intArray", SqlDbType.Structured) { TypeName = "dbo.IntArray" });
var sqlQuery = "spProcedure1 #InArray";
return Database.SqlQuery<int>(sqlQuery, sqlParameters.ToArray()).ToList();
I have this sql statement:
selectAllUsersByCriteria = connection.prepareStatement(
"SELECT * FROM Users WHERE ? = ?" );
And the follow method running the statement:
public ArrayList<User> getUsersByCriteria(String 1criteria, String 2criteria)
{
ArrayList<User> results = null;
ResultSet resultSet = null;
try
{
selectAllUsersByCriteria.setString( 1, 1criteria);
selectAllUsersByCriteria.setString( 2, 2criteria);
// executeQuery returns ResultSet containing matching entries
resultSet = selectAllUsersByCriteria.executeQuery();
results = new ArrayList< User >();
while ( resultSet.next() )
{
results.add( new User( resultSet.getString( "userName" ),
resultSet.getString( "Password" ),
resultSet.getBoolean( "AdminRights" ),
resultSet.getDouble( "Balance" )
) );
} // end while
} // end try
catch ( SQLException sqlException )
{
sqlException.printStackTrace();
} // end catch
finally
{
try
{
resultSet.close();
} // end try
catch ( SQLException sqlException )
{
sqlException.printStackTrace();
close();
} // end catch
} // end finally
return results;
}
It doesn't work. I figure it is the first ? that is the issue. Isn't it possible to set the WHERE ? as a ?. Can it be solved in another way.
It is a table I want to show, but it should only be show the users follow it meet the two criteria.
You would need to inject the column name directly into the string. That would open you up to a SQL injection attack, so I'd recommend querying (and probably caching) the table's schema info (specifically found in INFORMATION_SCHEMA.COLUMNS).
This way you can make sure that your user-submitted column name matches one of the column names in your table before injecting it into the script by seeing if it's in your list of available columns.
So I have a really frustrating build error I have been staring at for the past hour or two. It involves one of my functions in my linked list program. It thinks I have statements outside the function when they are clearly inside, and thinks the { : } ratio is off. Am I missing something really simple?
// Index returns the location of element e. If e is not present,
// return 0 and false; otherwise return the location and true.
func (list *linkedList) Index(e AnyType) (int, bool) {
var index int = 0
var contain bool = false
if list.Contains(e) == false {
return 0, false
}
for int i := 0; i < list.count; i++ { \\175
list.setCursor(i)
if list.cursorPtr.item == e {
index = list.cursorIdx
contain = true
}
}
return index, contain \\182
} \\183
Build errors
./lists.go:175: syntax error: unexpected name, expecting {
./lists.go:182: non-declaration statement outside function body
./lists.go:183: syntax error: unexpected }
I appreciate any help. Thank you.
Looks like it's all line 175's fault, should be
for i := 0; i < list.count; i++ {
note I removed int
I am new to ActionScripting but I have done some Java. I was told they are kinda similar. I am coding my swf file with some AS3 integrated.
function init():void{
// do something
}
function init(var string:String):String{
// do something else
}
is this not allowed in AS? If not, is there another way of handling it besides?
Thanks in advance.
Yes, you can override functions. But the example you gave is not overriding - it's overloading. For overriding a function, you basically just create a function with the same signature and everything in a subclass and add the word "override" right before it.
You can't directly overload a function though. If you want a variable number of parameters, you have to use optional parameters instead. Like this:
function init(str:String = null):String
{
if (str == null)
{
// do one thing
return null;
}
else
{
// do another thing
return "someString";
}
}
And that's about the best you're going to be able to do in AS3. The inability to overload functions, at least strictly speaking, is a fairly common complaint and obvious shortcoming of the language.
Do you mean method overloading? Actionscript, sadly, does not support this.
To get around it, you can use default parameters, or just make your parameters a bit less constraining. This answer has some details on that.
You could try this:
function init(var string:String = "Default value"):String{
// do something
}
Actionscript does not support method overloading. However, based on the answer to this question you have other options.
If you just want to be able to accept any type, you can use * to
allow any type:
function someFunction( xx:*, yy:*, flag:Boolean = true )
{
if (xx is Number) {
...do stuff...
} else if (xx is String) {
...do stuff...
} else {
...do stuff...
}
}
If you have a large number of various parameters where order is
unimportant, use an options object:
function someFunction( options:Object )
{
if (options.foo) doFoo();
if (options.bar) doBar();
baz = options.baz || 15;
...etc...
}
If you have a variable number of parameters, you can use the ...
(rest) parameter:
function someFunction( ... args)
{
switch (args.length)
{
case 2:
arr = args[0];
someBool = args[1];
xx = arr[0];
yy = arr[1];
break;
case 3:
xx = args[0];
yy = args[1];
someBool = args[2];
break;
default:
throw ...whatever...
}
...do more stuff...
}
For cases where you need to call a common function to a number of
classes, you should specify the interface common to each class:
function foo( bar:IBazable, flag:Boolean )
{
...do stuff...
baz = bar.baz()
...do more stuff...
}