Is it possible in LUA to execute a function like foo("param1, param2, param3, param4"), and have it detect it as foo(param2, param2, param3, param4)
Why?
I have a scenario where a function can receive as many parameters as I wish, and they can't be sent as a list (It's in CoronaSDK, so I can't really modify the source, and have to adapt to it). So, sometimes I'll have to send 3 parameters, while sometimes I'll be sending 100. Is there anyway of doing this?
they can't be sent as a list (It's in CoronaSDK, so I can't really modify the source, and have to adapt to it)
Sure it can. Watch:
function CallWithParametersInAList(FunctionToCall, paramsInList)
return FunctionToCall(unpack(paramsInList))
end
See? Every array element in paramsInList will be unpacked into arguments to FunctionToCall. Also, every return value from FunctionToCall will be returned.
see
function test(a)
print("this is lua test function."..a);
end
CallWithParametersInAList(test,{33333});
OUTPUT
this is lua test function.33333
You can call a lua function with as many parameters as you want. If the function expects more parameters, they will be set to nil. If the function expects too few parameters, the extra parameters sent will get ignored.
For example:
function f(a, b, c)
print(a, b, c)
end
f(1, 2) -- prints: 1 2 nil
f(1, 2, 3) -- prints: 1 2 3
f(1, 2, 3, 4, 5) -- prints: 1 2 3
edit:
If you must get the parameters from a string and those parameters include things like tables and functions, you have little option but to get the string parsed by loadstring function:
-- s contains the parameters
s = '1,2,{1,2,3}'
-- f is the function you want to call
loadstring('f(' .. s .. ')')() -- prints: 1 2 table: 0061D2E8
I'm not sure about CoronaSDK, but the loadstring function tends to be a bit slow. Try to avoid it if possible.
One of the best methods, in my opinion(and the one I use) is something like this:
function Call( ... )
-- All passed arguments are stored in a default table named arg
table.foreach( arg, print )
end
And, here's a working example on codepad - oDmVZ209.
I'd second Nicol Bolas that you are probably trying to solve the wrong problem, but if you still want to parse the string and turn it into a list of parameters, here is one way to do this (loadstring is not available in Corona environment; obviously this doesn't handle any type of hierarchical data):
function str2list(s)
local parms = {}
for p in s:gmatch("([^,]+),?") do table.insert(parms, p) end
return unpack(parms)
end
print(str2list("param1, param2, param3, param4"))
Related
Learning elm but don't get what author means by the below:
The reason we can avoid writing the parenthesis is because function
application associates to the left.
Any values or functions, specified after the function name, will be associated with the function as it's arguments automatically, that's really all it means.
In language, like JavaScript, you can explicitly distinguish the usage of a function, as an expression:
function foo (message) {
return message
}
console.log(foo) // Function as expression.
console.log(foo('Hello')) // Function application with result: "Hello"
In Elm this behaviour does not require parentesis.
foo message =
message
foo -- Function as expression.
foo "Hello" -- Function application with result: "Hello"
It's not like in JavaScript at all, when you want to apply the function and do something with result. Here you will have to tell the compiler explicitly, that (foo "Hello") is a single argument for String.toUpper
String.toUpper (foo "Hello") -- "HELLO"
The parentheses in question is ((divide 5) 2). My interpretation of that sentence is that you can write ((divide 5) 2) as divide 5 2 because divide 5 2 is evaluated from the left first, i.e. divide 5 -> divide5 then divide5 2 -> 2.5.
Though I can't see how else it could be evaluated! Neither 5 2 nor divide 2 then divide2 5 make sense.
I have a custom keyword in the robot framework which counts the items of a list. This works already in my underlying python file and prints the number 5 when five elements exists in a list.
Then I want to bring this value to the robot framework. But instead of a number I get:
${N_groups} is <built-in method count of list object at 0x03B01D78>
The code of the robot file:
*** Test Cases ***
Count Groups
${N_groups} Setup Groups Count Groups
log to console ${N_groups}
How to get item-count of the list as an integer value?
Here is a part of my python file:
#keyword(name="Count Groups")
def count_groups(self):
N = self.cur_page.count_groups()
return N
And a more low level python file:
def count_groups(self):
ele_tc = self._wait_for_treecontainer_loaded(self._ef.get_setup_groups_treecontainer())
children_text = self._get_sublist_filter(ele_tc, lambda ele: ele.find_element_by_tag_name('a').text,
True)
return children_text.count
Your function count_groups is returning children_text.count. children_text is a list, and you're returning the count method of that object, which explains the error that you're seeing. It's no different than if you did something like return [1,2,3].count.
Perhaps you intend to actually call the count function and return the results? Or, perhaps you are intending to return the length of the list? It's hard to see what the intent of the code is.
In either case, robot is reporting exactly what you're doing: you're returning a reference to a function, not an integer. My guess is that what you really want to do is return the number of items in the list, in which case you should change the return statement to:
return len(children_text)
I have a function that has multiple inputs, and would like to use SFrame.apply to create a new column. I can't find a way to pass two arguments into SFrame.apply.
Ideally, it would take the entry in the column as the first argument, and I would pass in a second argument. Intuitively something like...
def f(arg_1,arg_2):
return arg_1 + arg_2
sf['new_col'] = sf.apply(f,arg_2)
suppose the first argument of function f is one of the column.
Say argcolumn1 in sf, then
sf['new_col'] = sf['argcolumn1'].apply(lambda x:f(x,arg_2))
should work
Try this.
sf['new_col'] = sf.apply(lambda x : f(arg_1, arg_2))
The way i understand your question (and because none of the previous answers are marked as accepted), it seems to me that you are trying to apply a transformation using two different columns of a single SFrame, so:
As specified in the online documentation, the function you pass to the SFrame.apply method will be called for every row in the SFrame.
So you should rewrite your function to receive a single argument representing the current row, as follow:
def f(row):
return row['column_1'] + row['column_2']
sf['new_col'] = sf.apply(f)
To me, adding "Dump" to the end of an expression doesn't seem to do anything different, at least for seeing rows in a table. Can you point me to an example of where it is handy?
If you are just working with an expression, there is no reason to call Dump—it's called automatically. But, in the language selection box, LINQPad allows allows the selection of Statements and Program. Once you select one of those, you don't get any Dump output unless you call it.
With Statements or Programs, you might want to call Dump on multiple times. In those cases, it is handy to pass the Description parameters so you can distinguish the output.
There are also other parameters you can use to shape the output, such as depth, which limits the substructure details.
Simple example (Language=C# Statements):
var integers = Enumerable.Range(1,10);
integers.Select(i => new { i, v = i * i}).Dump("Squares");
integers.Select(i => new { i, v = i * i * i}).Dump("Cubes");
var output = "λ is awesome";
Encoding.UTF8.GetBytes(output)
.Dump("UTF-8");
Encoding.GetEncoding("Windows-1252").GetBytes(output)
.Dump("Windows-1252 (lossy)");
I've been given some code to go through and find problems and things that could be improved and changed (it's a homework task, but this question is unrelated to the task itself), part of the code is:
Function CheckIfSameCell(ByVal FirstCellPosition As CellReference, ByVal SecondCellPosition As CellReference) As Boolean
Dim InSameCell As Boolean
InSameCell = False
If FirstCellPosition.NoOfCellsSouth = SecondCellPosition.NoOfCellsSouth And FirstCellPosition.NoOfCellsEast = SecondCellPosition.NoOfCellsEast Then
InSameCell = True
End If
CheckIfSameCell = InSameCell
End Function
I can't understand why the InSameCell is variable is created, when it can just be assigned to the function name CheckIfSameCell?
Or just use return statements as in the following?
Function CheckIfSameCell(ByVal FirstCellPosition As CellReference, ByVal SecondCellPosition As CellReference) As Boolean
If FirstCellPosition.NoOfCellsSouth = SecondCellPosition.NoOfCellsSouth And FirstCellPosition.NoOfCellsEast = SecondCellPosition.NoOfCellsEast Then
Return True
End If
Return False
End Function
I can understand not returning the expression in the If statement directly, to increase readability.
I know that assigning a return value to the Function name doesn't exit the function, whereas Return does, but is it just a person's style, or is there any advantage to the first version (IMO, the second is more readable)?
Maybe there used to be more checks, where value of InSameCell could change several times and only then get returned. Using return then would change behaviour.
Maybe the author wanted to avoid the tedious renaiming. You know, when you want to rename a function, and you use that function's name many times within its own body, then you have many places to replace, whereas when you introduce a variable you will only have one place to change the name in. (I know the IDE will properly do that for you; but that was not the case in VB6, and habits are difficult to break.)
Maybe the author was much more familiar with VB6 that didn't have return.
Maybe it was a matter of style or policy.
Anyway, I would write it as:
Function CheckIfSameCell(ByVal FirstCellPosition As CellReference, ByVal SecondCellPosition As CellReference) As Boolean
Return FirstCellPosition.NoOfCellsSouth = SecondCellPosition.NoOfCellsSouth AndAlso FirstCellPosition.NoOfCellsEast = SecondCellPosition.NoOfCellsEast
End Function
Assigning the result to the function name is an old style used in VB6 and should not be used any more in VB.NET. Use Return value!
Personally I dislike statements in the style
If condition Then
Return True
Else
Return False
End If
They are just stupid, since condition already yields the return value! Better:
Return condition
It is also the solution chosen by GSerg.
Nobody would write
If x + y = 0 Then
Return 0
ElseIf x + y = 1 Then
Return 1
ElseIf x + y = 2 Then
Return 2
ElseIf x + y = 3 Then
Return 3
...
But some people are constantly doing it when the expression is of type Boolean. I think that they do not realize that conditions are equivalent to arithmetical expressions. They are just arithmetic with Booleans instead of arithmetic with numbers.
Another misconception is that an If-statement requires some comparison like If x > 0 Then. If they have a Boolean variable b they write If b = True Then. But all the If-statement needs is a Boolean value given by a Boolean expression. This expression can be as simple as querying a variable: If b Then.
Why does this work? Because if b is True then b = True yields True and if b is False then b = True yields False. So, b = True is very much like saying x * 1. Of course, this is the same as just x.
The second method is more readable, I concur. It also happens to be my preference for returning out of methods. I really cannot think of a single downside to the latter in comparision, but can for the former. What happens if the method gets longer and someone forgets to set a Boolean flag? A subtle bug would be born. Additionally, it takes more code to write as well. In the latter approach, the code won't compile if it is missing a return, and it also will be shorter.
The only time you need local variables for the return type is when the routine needs to do some other work after the return value is first determined. In the example you post, this is not the case.
Code Complete, 2nd Edition agrees on page 391:
Use a return when it enhances readability In certain routines, once
you know the answer, you want to return it to the calling routine
immediately. If the routine is defined in such a way that it doesn’t
require any further cleanup once it detects an error, not returning
immediately means that you have to write more code.
NOTE: As other answers [1,2] have mentioned, you can reduce the method to a single code statement. Also using AndAlso should help speed up the evaluation by short-circuiting the logical expression early if the first part is false:
Return FirstCellPosition.NoOfCellsSouth = SecondCellPosition.NoOfCellsSouth
AndAlso FirstCellPosition.NoOfCellsEast = SecondCellPosition.NoOfCellsEast
There is one important thing with return and assigning value the the function name. If you (for whatever twisted reason) would like to write something like that
Public Function TestFunct() as Boolean
Dim testVar as Boolean = True
If testVar then
TestFunct = True
Else
TestFunct = False
EndIf
'do more stuff here
...
TestFunct = False
End Function
It will always return false. If you use returns instead it the execution will stop and the function will return correct value.
You might use a variable if for some reason it needs to appear on the right-hand side of an assignment, and you don't want to cause a recursion:
Dim Function F() As Boolean
F = True
If a = b Then
F = Not F()
End If
End Function
In short - Yes your last example is quite valid.
However, most examples used in homework are either used to show other teaching examples. The code in the homework sheet merely shows the basics of using functions in the traditional way and your 2nd example shows the next learning step and is the most compact way of achieving the desired result.
Also, the 1st example could also be used to re-enforce lessons learned earlier - e.g. about assigning variables, use of booleans etc.
One of the best ways to improve your coding skills is to repeatedly practice what you have learned.