JQassistant rule for TestMethodWithoutAssertion with non-Junit assert methods - junit

Our project uses assert methods from assertj library as well in some of the unit test methods. So the current cypher rule to search for assert method doesn't identify assert methods like below and flags them as violations.
assertThat("x").isEqualTo("Y"); in the unit test methods.
how to modify the script to consider any "assert*" invocations from unit test method.
<cypher><![CDATA[
MATCH
(c:Type:Class)-[:DECLARES]->(m:Method:JunitTestMethod),
(m)-[:INVOKES*..10]->(assert:Method)
WHERE
assert.signature =~ "void assert.*"
OR assert.signature =~ "void fail.*"
OR assert.signature =~ "void verify.*"
SET
m:JunitTestWithAssert
RETURN
c.fqn AS TestClass, m.name AS TestMethodWithAssert
]]></cypher>
Sample Test method :
#Test
public void testAssertWithDiffLibrary() {
String testName = "Hello";
assertThat(testName).isEqualTo("Hello");
}
Note : Tried adding a where clause "OR assert.name =~ ".assert."" but doesn't detect these asserts.

It would be
"OR assert.name =~ ".*assert.*""
But it has the drawback that every method containing assert in name is marked.
Note the stars after the dots.
Given that you want to use the provided "junit4:TestMethodWithoutAssertion" constraint, I would suggest the AssertJ version of the http://buschmais.github.io/jqassistant/doc/1.3.0/#junit4:AssertMethod concept:
<concept id="assertj:AssertMethod">
<description>Labels all assertion methods declared by org.assertj.core.api.Assertions with "Assertj" and "Assert".</description>
<cypher><![CDATA[
MATCH
(assertType:Type)-[:DECLARES]->(assertMethod)
WHERE
assertType.fqn = 'org.assertj.core.api.Assertions'
and assertMethod.signature =~ '.*assertThat.*'
SET
assertMethod:Assertj:Assert
RETURN
assertMethod
]]></cypher>
</concept>
So your group definition now is as follows:
<group id="default">
<includeConcept refId="assertj:AssertMethod" />
<includeConstraint refId="junit4:TestMethodWithoutAssertion" />
</group>
Now your provided sample method is handled correctly.

Have a look at the Spring PetClinic demo application: it provides a concept "assertj:AssertMethod" in assertj.adoc:
[[assertj:AssertMethod]]
[source,cypher,role=concept]
.Mark all assertThat methods of 'org.assertj.core.api.Assertions' with "AssertJ" and "Assert".
----
MATCH
(assertType:Type)-[:DECLARES]->(assertMethod)
WHERE
assertType.fqn = 'org.assertj.core.api.Assertions'
and assertMethod.signature =~ '.* assertThat.*'
SET
assertMethod:AssertJ:Assert
RETURN
assertMethod
----
which is then referenced by a constraint in test.adoc:
[[test:TestMethodWithoutAssertion]]
[source,cypher,role=constraint,requiresConcepts="junit4:TestMethod,assertj:AssertMethod,spring-test-web:Assert"]
.All test methods must perform at least one assertion (within a call hierarchy of max. 3 steps).
----
MATCH
(testType:Test:Type)-[:DECLARES]->(testMethod:Test:Method)
WHERE
NOT (testMethod)-[:INVOKES*..3]->(:Method:Assert)
RETURN
testType AS DeclaringType,
testMethod AS Method
----

Related

PowerShell Function parameters - by reference or by value?

So, I tried looking up the answer to this question, and found the generally available answer is that PowerShell passes parameters by value. These generally accepted solutions all post sample code to prove their assertions, similar to the following:
Function add1 ($parameter)
{
Write-Host " In Function: `$parameter = $parameter"
Write-Host " In Function: `$parameter += 1"
$parameter += 1
Write-Host " In Function: `$parameter = $parameter"
}
cls
$a = 1
Write-Host "Before function: `$a = $a"
add1 $a
Write-Host " After function: `$a = $a"
This gives the results:
Before function: Run Command: $a = 1
In Function: $parameter: 1
In Function: Run Command: $parameter += 1
In Function: $parameter: 2
After function: $a: 1
Thus proving that parameters are passed by value, right? Well, I was having a heck of a time troubleshooting a function I was writing. The function added a couple of additional NoteProperty items to a PSCustomObject I pass in to the function, and my program would throw all sorts of errors saying that the NoteProperty already existed, even though I had not modified the original object in the parent scope, only inside the function.
So, I set up a version of the above code to test using parameter of type [PSCustomObject], like so:
Function F1($Obj)
{
'Function F1: Run command: $Obj.FirstValue = 11'
$Obj.FirstValue = 11
" `$Obj.Name: $($StartObject.Name)"
" `$Obj.FirstValue: $($StartObject.FirstValue)"
" `$Obj.SecondValue: $($StartObject.SecondValue)"
}
Function F2($Obj)
{
'Function F2: Run command: $Obj | Add-Member -MemberType NoteProperty -Name SecondValue -Value 33'
$obj | Add-Member -MemberType NoteProperty -Name SecondValue -Value 33
" `$Obj.Name: $($StartObject.Name)"
" `$Obj.FirstValue: $($StartObject.FirstValue)"
" `$Obj.SecondValue: $($StartObject.SecondValue)"
}
cls
Remove-Variable StartObject
"Main script: Run command: `$StartObject = [PSCustomObject]#{Name='Original';FirstValue=22}"
$StartObject = [PSCustomObject]#{Name='Original';FirstValue=22}
" `$StartObject.Name: $($StartObject.Name)"
" `$StartObject.FirstValue: $($StartObject.FirstValue)"
" `$StartObject.SecondValue: $($StartObject.SecondValue)"
'Run command: F1 $StartObject'
" "
F1 $StartObject
" "
"Main script: `$StartObject.Name: $($StartObject.Name)"
" `$StartObject.FirstValue: $($StartObject.FirstValue)"
" `$StartObject.SecondValue: $($StartObject.SecondValue)"
"Run command: F2 $StartObject"
" "
F2 $StartObject
" "
"Main script: `$StartObject.Name = $($StartObject.Name)"
" `$StartObject.FirstValue = $($StartObject.FirstValue)"
" `$StartObject.SecondValue = $($StartObject.SecondValue)"
This messy piece of programming produces the following output:
Main script: Run command: $StartObject = [PSCustomObject]#{Name='Original';FirstValue=22}
$StartObject.Name: Original
$StartObject.FirstValue: 22
$StartObject.SecondValue:
Run command: F1 $StartObject
Function F1: Run command: $Obj.FirstValue = 11
$Obj.Name: Original
$Obj.FirstValue: 11
$Obj.SecondValue:
Main script: $StartObject.Name: Original
$StartObject.FirstValue: 11
$StartObject.SecondValue:
Run command: F2 #{Name=Original; FirstValue=11}
Function F2: Run command: $Obj | Add-Member -MemberType NoteProperty -Name SecondValue -Value 33
$Obj.Name: Original
$Obj.FirstValue: 11
$Obj.SecondValue: 33
Main script: $StartObject.Name = Original
$StartObject.FirstValue = 11
$StartObject.SecondValue = 33
These results clearly show that when [PSCustomObject] parameters are used, any modifications within the function take place on the passed object, thus pass by reference. This behavior happens regardless of defining my parameters as [PSCustomObject]$Obj, or leaving them untyped. This is not a huge problem in and of itself, but the problem is that I was unable to find this little gem of information in any of the documentation I looked through. I checked a few tutorial sites and Microsoft's own documentation on Function Parameters, but did not see this exception.
So, my question boils down to this: Has anyone found any documentation to support my theory that while most parameters default to passing by value, they are passed by reference when objects are concerned?
I am perfectly willing to believe that I missed some documentation somewhere, so please...point it out and show me the error of my ways! :)
Thanks very much
Note: The following also applies to assigning one variable to another: $b = $a ...
* makes $b reference the very same object that $a does if $a's value is an instance of a reference type,
* makes $b receive an independent copy of $a's value if the latter is an instance of a value type.
PowerShell uses by-(variable)-value passing by default; that is, the content of a variable is passed, not a reference to the variable itself.
Extra effort is needed if you want by-(variable)-reference passing, i.e. if you want to pass a reference to a variable itself, allowing the callee to both get the variable's content and to assign new content; in the simplest form, you can use a [ref]-typed parameter (akin to ref parameters in C#). However, note that this technique is rarely necessary in PowerShell.
Whether that content is a copy of what the caller sees or a reference to the very same object depends on the data type of the content:
If the content happens to be an instance of a .NET reference type - as [pscustomobject] is - that content is an object reference, and the callee can therefore potentially modify that object, by virtue of seeing the very same object as the caller.
If you want to pass a copy (clone) of a reference-type instance, note that there is no universal mechanism for creating one:
You can create copies of instances of types if they implement the System.ICloneable interface by calling their .Clone() method, but note that it is up to the implementing type whether to perform shallow or deep cloning[1]; it is for that reason that use of this interface is discouraged; in practice, types that do implement it typically perform shallow cloning, notably arrays, array lists (System.Collections.ArrayList) and hashtables (but note that an [ordered] hashtable (System.Collections.Specialized.OrderedDictionary) doesn't implement ICloneable at all.
Additionally, in PowerShell, you can call .psobject.Copy() on instances of type [pscustomobject] to create a shallow copy. (Do not use this method on objects of any other type, where it will effectively be a no-op.) Similarly, individual .NET types may implement custom cloning methods.
If, by contrast, that content is an instance of a .NET value type - e.g., [int] - or a
string[2], an independent copy of that instance is passed.
This distinction is fundamental to .NET, not specific to PowerShell; it is also how arguments are passed in C#, for instance.
To determine whether a given variable's value is an instance of a value type or a reference type, use something like the following:
1, (Get-Date), (Get-Item /) | # sample values
foreach {
'{0} is of type {1}; is it a value type? {2}' -f $_,
$_.GetType(),
$_.GetType().IsValueType
}
You'll see something like:
1 is of type System.Int32; is it a value type? True
4/30/2020 12:37:01 PM is of type System.DateTime; is it a value type? True
/ is of type System.IO.DirectoryInfo; is it a value type? False
If you look up the documentation for a given .NET type, say System.DateTime, the inheritance information will start with Object -> ValueType for value types; in C# terms, a value type is either a struct or an enum, whereas a reference type is a class.
Terminology and concepts:
There are two unrelated concepts at play here, and the fact that they both use the terms (by-)value and (by-)reference can get confusing:
By-(variable)-value vs. by-(variable)-reference parameter-passing is a data-holder (variable) concept:
It describes whether, on parameter passing, a variable's value is passed (by value) or a reference to the variable itself[3] (by reference).
Reference types vs. value types is purely a data concept:
That is, for technical reasons, any object in .NET is either an instance of a value type (stored on the stack) or a reference type (stored on the heap). Instances of the former are directly stored in variables, whereas the latter are stored by way of a reference. Therefore, copying a variable value - e.g., in the context of by-value parameter-passing - means:
either: making a copy of a value-type instance itself, resulting in an independent data copy.
or: making a copy of a reference-type instance reference; a copy of a reference still points to the same object, however, which is why even by-variable-value passed reference-type instances are directly seen by the callee (by way of their reference copy).
[1] Shallow cloning means that property values that are reference-type instances are copied as-is - as references - which means that the clone's property value again references the very same object as the original. Deep cloning means that such property values are cloned themselves, recursively. Deep cloning is expensive and isn't always possible.
[2] A string ([string]) is technically also an instance of a reference type, but, as an exception, it is treated like a value type; see this answer for the rationale behind this exception.
[3] Another way of thinking about it: a reference (pointer) to the location where the variable stores its value is passed. This allows the callee to not only access the variable's value, but also to assign a (new) value.

What's the difference these two function calling conventions?

Functions can be called in a couple ways:
say(1, 2, 3) # 123
say: 1, 2, 3 # (1, 2, 3)
The latter seems to pass a Positional, but apart from that I don't know how else they differ. Are there any differences that are important to know? What types of situations would you use one over the other?
#jjmerelo's answer covers the basics. This complementary answer, which aims at being somewhat exhaustive but hopefully not exhausting, covers traps, rare cases, and advice.
foo: valuea, valueb, ...
Surprisingly perhaps, this is not a call of a sub or method called foo.
Instead it's a statement that begins with a label, foo:.
The say: line in your question won't work in an ordinary program:
say: <a b c>; # Useless use of constant value a b c ...
The "Useless use" warning means the <a b c> doesn't get used in a useful way. The say: isn't doing anything with the list of values. It's just a label that doesn't do anything.
Presumably you are using something like the Perl 6 REPL. The REPL automatically says the last value in a line if it isn't otherwise used, thus making the line appear to work without a warning.
.a-method:
If a postfix method call using the form .a-method has no arguments other than the invocant (the argument to the left of the ., or the current topic if there isn't an explicit invocant) then you can just write it in the form:
42.say ;
You can optionally append a colon:
42.say: ;
There's no good reason to, but it's consistent with:
.a-method: arg2, arg3, ...
If you want to supply one or more arguments (other than the invocant) to a postfix .a-method call, then you have to pick one of two ways to introduce them.
One way is to write a colon immediately after the method name, before the argument(s). There must be no space between the method name and colon, and there must be space after the colon before the method argument(s).1
For example, the following uses a colon before the Numeric argument in the following method call:
say <abc 2 def ghi> .first: Numeric ; # 2
In the above line the method call expression (.first: Numeric) ends at the statement terminator (;). If there's an enclosing sub-expression such as an array subscript then the method call expression ends at the end of that sub-expression:
say .[1 + .first: Numeric] given <abc 2 def ghi> ; # ghi
The argument list of a colon form method call is also brought to a close by a valid statement modifier like given:
say .first: Numeric given <abc 2 def ghi> ; # 2
a-sub arg1, arg2, ...
This is the corresponding form for subroutine calls. The only format differences are that the sub has no invocant or . before the sub name and you must omit the colon after the sub name.
.a-method( arg2, arg3, ... )
a-sub( arg1, arg2, ... )
The other common form used for both method and sub calls is to immediately follow the method or sub name with parens to delimit arguments. The opening paren must immediately follow, without any space between the routine name and (.
Here's parens used with the .first method:
say 1 + .first(Numeric) given <abc 2 def ghi> ; # 3
This has the advantage that it's arguably prettier than the alternative of using outer parens:
say 1 + (.first: Numeric) given <abc 2 def ghi> ; # 3
If you want to put a sub call directly inside a double quoted string, you need to prefix the sub name with an & sigil and use the postfix parens form:
my #array = <abc 2 def ghi> ;
say "first number is &first(Numeric,#array)" ; # first number is 2
To put in a method call, you again have to use the postfix parens form, and you must also provide an explicit invocant (you can't just write "Some text .a-method()"):
my #array = <abc 2 def ghi> ;
say "first number is #array.first(Numeric)" ; # first number is 2
If there are no arguments (other than the invocant for a method call) you still need to use this form with empty parens if you want to interpolate a sub or method call in a string:
my #array = <abc 2 def ghi> ;
say "no method call #array[3].uc" ; # no method call ghi.uc
say "with method call #array[3].uc()" ; # with method call GHI
say "&rand"; # &rand
say "&rand()"; # 0.929123203371282
.a-method ( arrgh, arrgh, ... ) ;
This won't work.
Because the .a-method isn't followed by a colon, the method call is considered complete.
That means the next thing must be either an expression/statement ender like ;, or a postfix operator that will operate on the result of the method call, or an infix operator that will operate on the result and some following argument.
But ( arrgh, arrgh, ... ) is none of these. So you get a "Two terms in a row" compilation error.
.a-method:( arrgh, arrgh, ... ) ;
.a-method: ( arrgh, arrgh, ... ) ;
In general, DO NOT MIX use of a : with use of parens around arguments as part of a method call. There is no good reason to do so because it will either not work, or work only by accident, or work but very likely confuse readers.
Doing so without a space between the colon and opening paren yields a cryptic compilation error:
This type (QAST::WVal) does not support positional operations
Leaving a space appears to work -- but typically only by luck:
say .first: (Numeric) given <abc 2 def ghi> ; # 2
The (Numeric) is a single value in parens which yields Numeric so this line is the same as:
say .first: Numeric given <abc 2 def ghi> ; # 2
But if there are two or more arguments in parens, things will go awry. Use one of these forms:
say .first: Numeric, :k given <abc 2 def ghi> ; # 1
say .first(Numeric, :k) given <abc 2 def ghi> ; # 1
which correctly yield the array index ("key") of the 2 element rather than:
say .first: (Numeric, :k) given <abc 2 def ghi> ; # Nil
which yields Nil because the .first method doesn't do anything useful with a single argument that's a list of the form (Numeric, :k).
Of course, you may occasionally want to pass a single argument that's a list of values in parens. But you can do so without using a colon. For the sake of clarity, it's my advice that you instead write this as:
invocant.a-method(( valuea, valueb, ... ));
a-sub ( arrgh1, arrgh2, ... ) ;
As just explained for method calls, this passes ONE argument to a-sub, namely the single list ( arrgh1, arrgh2, ... ) which will seldom be what the writer means.
Again, my advice is to instead write this as:
`a-sub( valuea, valueb, ... ) ;`
or:
`a-sub valuea, valueb, ... ;`
if you mean to pass multiple arguments, or if you wish to pass a list as a single argument, then:
`a-sub(( valuea, valueb, ... )) ;`
.a-method : arrgha, arrghb, ...
a-sub : arrgha, arrghb, ...
For the method form this will net you a "Confused" compilation error.
The same is true for the sub form if a-sub takes no arguments. If a-sub takes arguments you'll get a "Preceding context expects a term, but found infix : instead" compilation error.
.&a-sub
There's a call form which lets you call a routine declared as a sub -- but use the .method call syntax. The following feeds the "invocant" qux on the left of the dot as the first argument to a sub called a-sub:
qux.&a-sub
Use a : or parentheses as usual to pass additional arguments to a-sub:
sub a-sub ($a, $b) { $a == $b }
say 42.&a-sub(42), 42.&a-sub(43); # TrueFalse
say 42.&a-sub: 42; # True
(In my original version of this section I wrote that one can not pass additional arguments. I had tested this and thought one could not. But I must have just gotten confused by something. #Enheh's comment led me to retest and discover that one can pass additional arguments just as with ordinary method calls. Thank you #Enheh. :))
a-method( invocant: arg2, arg3, ... )
a-method invocant: arg2, arg3, ...
Called "Indirect object notation" in the design docs, these formats are an undocumented and very rarely seen form of method call in which the call mimics the method declaration -- the method name comes first and then the invocant followed by a colon:
say first <abc 2 def ghi>: Numeric ; # 2
Note that say is a sub call because the next token, first, isn't followed by a colon. In contrast first is a method call because the token after it is followed by a colon.
Footnotes
1 All comments about spaces/spacing in this answer ignore unspacing.
As Raiph tells you above, say: is a label. So you didn't say anything (even though you thought you did) and -- outside use of the REPL -- the compiler will complain that your use of <a b c> was useless:
say: <a b c>; # OUTPUT: «WARNINGS for <tmp>:␤Useless use of constant value a b c in sink context (lines 1, 1, 1, 1, 1, 1)␤»
However, you often can use a : notation instead of parentheses in method calls. Consider the four routine calls below (two subroutine calls then two method calls):
my #numbers = (33, 77, 49, 11, 34);
say map *.is-prime, #numbers ; # simplest subroutine call syntax
say map( *.is-prime, #numbers ); # same meaning, but delimiting args
say #numbers.map( *.is-prime ) ; # similar, but using .map *method*
say #numbers.map: *.is-prime ; # same, but using : instead of parens
These sentences will all return the same (False False False True False).
In general, as you see above with map, you can use () in method calls wherever you would use :, but the opposite is not true; : can be used only in method calls.
Use () if the arguments need to be delimited precisely, as Raiph comments below.
This answer focuses on the basics. See Raiph's answer for more exhaustive coverage of the precise details of routine call syntax. (As an important example, the meaning of these calls normally changes if there's any spaces between the routine name and the colon (:) or opening parenthesis (()).

Perl 6: how to check `new` for invalid arguments?

What is the simplest way to check if invalid arguments are passed to the constructor method new?
use v6;
unit class Abc;
has Int $.a;
my $new = Abc.new( :b(4) );
The ClassX::StrictConstructor module should help. Install it with zef install ClassX::StrictConstructor and use it like so:
use ClassX::StrictConstructor;
class Stricter does ClassX::StrictConstructor {
has $.thing;
}
throws-like { Stricter.new(thing => 1, bad => 99) }, X::UnknownAttribute;
TLDR; If you are just worried about someone accidently mis-typing :a(4) as
:b(4), it might be better to just mark $.a as required.
class ABC {
has Int $.a is required;
}
ABC.new( :b(4) ); # error
# The attribute '$!a' is required, but you did not provide a value for it.
A quick hack would be to add a submethod TWEAK that makes sure any named values that you don't specify aren't there. It doesn't interfere with the normal workings of new and BUILD, so the normal type checks work without having to re-implement them.
class ABC {
has Int $.a;
submethod TWEAK (
:a($), # capture :a so the next won't capture it
*% # capture remaining named
() # make sure it is empty
) {}
}
A slightly more involved (but still hacky) way that should continue to work for subclasses, and that doesn't need to be updated with the addition of more attributes:
class ABC {
has Int $.a;
submethod TWEAK (
*%_ # capture all named
) {
# get the attributes that are known about
# (should remove any private attributes from this list)
my \accepted = say self.^attributes».name».subst(/.'!'/,'');
# ignore any that we know about
%_{|accepted}:delete;
# fail if there are any left
fail "invalid attributes %_.keys.List()" if %_
}
}
Write a custom new
Add this method declaration to your class:
method new ( :$a is required ) { callsame }
The :$a binds to a named argument named a (i.e. a key/value pair whose key is 'a', eg. a => 4).
The is required that follows the parameter name makes the a argument mandatory.
Now calls that do not pass a named argument named a will be rejected:
Abc.new( :b(4) ) ; # Error: Required named parameter 'a' not passed
The body of your new new method calls callsame. It calls the new that your class inherits, namely Mu's new. This routine walks through your class and its ancestors initializing attributes whose names correspond to named arguments:
Abc.new( :a(4) ) ; # OK. Initializes new object's `$!a` to `4`
Abc.new( :a(4) ).a.say ; # Displays `4`
UPD: See Brad's answer for a simpler approach that just adds the is required directly to the existing attribute declaration in the class:
has Int $.a is required; # now there's no need for a custom `new`
ABC.new( :b(4) ); # The attribute '$!a' is required...
Note the shift in the error message from Required named parameter 'a' not passed to attribute '$!a' is required.... This reflects the shift from adding a custom new with a required routine parameter that then gets automatically bound to the attribute, to just adding the is required directly to the attribute.
If that's not enough, read on.
The default new
Accepts any and all named arguments (pairs). It then passes them on to other routines that are automatically called during object construction. You passed the named argument :b(4) in your example code. It was accepted and passed on.
Rejects any and all positional arguments (not pairs).
The new call in your original code was accepted because you only passed a named argument, so no positional arguments, thus satisfying the argument validation directly done by the default new.
Rejecting unknown named arguments (as well as any positional arguments)
method new ( :$a!, *%rest ) { %rest and die 'nope'; callsame }
The *%rest "slurps" all named arguments other than one named a into a slurpy hash. If it is not empty then the die triggers.
See also timotimo's answer.
Requiring positional arguments instead of named
It's almost always both simpler and better to use named parameters/arguments to automatically initialize corresponding object attributes as shown above. This is especially true if you want to make it easy for folk to both inherit from your class and add attributes they also want initialized during new.
But if you wish to over-rule this rule-of-thumb, you can require one or more positional parameters/arguments and call methods on the new object to initialize it from the passed argument(s).
Perhaps the simplest way to do this is to alter the attribute so that it's publicly writable:
has Int $.a is rw;
and add something like:
method new ( $a ) { with callwith() { .a = $a; $_ } }
The callwith() routine calls the inherited new with no arguments, positional or named. The default (Mu) new returns a newly constructed object. .a = $a sets its a attribute and the $_ returns it. So:
my $new = Abc.new( 4 );
say $new.a ; # Displays `4`
If you don't want a publicly writable attribute, then leave the has as it was and instead write something like:
method !a ( $a ) { $!a = $a } # Methods starting `!` are private
method new ( $a ) { with callwith() { $_!a($a); $_ } }

How to implement a basic Lua function in Conky?

I am trying to add a function to my Conky which prints the length of a string for debug purposes. The code, inside a file called test.lua, is pretty trivial:
function test(word)
return string.len(word)
end
...and I load it like this. In my conky.config section I have:
lua_load = '/home/xvlaze/test.lua',
lua_draw_hook_pre = 'test'
...in the conky.text section I have:
${lua test "fooo"}
...where test is the name of the function and fooo the string to test.
The expected result should be a printed 4 in Conky, but instead of that I get:
conky: llua_do_call: function conky_test execution failed: /home/xvlaze/test.lua:2: attempt to index a nil value (local 'string')
conky: llua_getstring: function conky_test didn't return a string, result discarded
I have browsed through the documentation, but I can't find anything. Does anybody know where the failure is?
Several guidances on how to implement functions in Conky:
First of all: YOU MUST USE conky_ BEFORE YOUR FUNCTION'S NAME.
Otherwise, you will get the following error when running your Conky:
attempt to call a nil value
Secondly: YOU MUST ALWAYS RETURN A VALUE.
I don't mind repeating it - it is crucial. Otherwise, you will get:
function foobar didn't return a string, result discarded
function_result
...in your terminal, and your Conky will be left empty of values related to your extra code. Nothing will be printed regarding your function.
Last but not least: YOU MUST ALWAYS CALL YOUR FUNCTION LIKE:
lua_load = '/path/to/function.lua',
-- Whatever content...
${lua function_name function_parameter1 function_parameterN} -- In case you use more than one parameter.
In summary, a dummy function template could be:
MAIN FILE (conky.conf):
conky.config = {
-- Whatever content... Lua styled comments.
lua_load = '/path/to/function.lua',
}
conky.text = [[
# Whatever content... In this section comments are started with '#'!
${lua function_name parameter}
]]
FUNCTION FILE:
function conky_function_name(parameter)
-- Whatever content... Remember this is Lua, not conky.text syntax. Always use '--' comments!
return whatever -- No return, no party. A function MUST always return something!
end

Pass by reference or pass by value? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
When learning a new programming language, one of the possible roadblocks you might encounter is the question whether the language is, by default, pass-by-value or pass-by-reference.
So here is my question to all of you, in your favorite language, how is it actually done? And what are the possible pitfalls?
Your favorite language can, of course, be anything you have ever played with: popular, obscure, esoteric, new, old...
Here is my own contribution for the Java programming language.
first some code:
public void swap(int x, int y)
{
int tmp = x;
x = y;
y = tmp;
}
calling this method will result in this:
int pi = 3;
int everything = 42;
swap(pi, everything);
System.out.println("pi: " + pi);
System.out.println("everything: " + everything);
"Output:
pi: 3
everything: 42"
even using 'real' objects will show a similar result:
public class MyObj {
private String msg;
private int number;
//getters and setters
public String getMsg() {
return this.msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getNumber() {
return this.number;
}
public void setNumber(int number) {
this.number = number;
}
//constructor
public MyObj(String msg, int number) {
setMsg(msg);
setNumber(number);
}
}
public static void swap(MyObj x, MyObj y)
{
MyObj tmp = x;
x = y;
y = tmp;
}
public static void main(String args[]) {
MyObj x = new MyObj("Hello world", 1);
MyObj y = new MyObj("Goodbye Cruel World", -1);
swap(x, y);
System.out.println(x.getMsg() + " -- "+ x.getNumber());
System.out.println(y.getMsg() + " -- "+ y.getNumber());
}
"Output:
Hello world -- 1
Goodbye Cruel World -- -1"
thus it is clear that Java passes its parameters by value, as the value for pi and everything and the MyObj objects aren't swapped.
be aware that "by value" is the only way in java to pass parameters to a method. (for example a language like c++ allows the developer to pass a parameter by reference using '&' after the parameter's type)
now the tricky part, or at least the part that will confuse most of the new java developers: (borrowed from javaworld)
Original author: Tony Sintes
public void tricky(Point arg1, Point arg2)
{
arg1.x = 100;
arg1.y = 100;
Point temp = arg1;
arg1 = arg2;
arg2 = temp;
}
public static void main(String [] args)
{
Point pnt1 = new Point(0,0);
Point pnt2 = new Point(0,0);
System.out.println("X: " + pnt1.x + " Y: " +pnt1.y);
System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);
System.out.println(" ");
tricky(pnt1,pnt2);
System.out.println("X: " + pnt1.x + " Y:" + pnt1.y);
System.out.println("X: " + pnt2.x + " Y: " +pnt2.y);
}
"Output
X: 0 Y: 0
X: 0 Y: 0
X: 100 Y: 100
X: 0 Y: 0"
tricky successfully changes the value of pnt1!
This would imply that Objects are passed by reference, this is not the case!
A correct statement would be: the Object references are passed by value.
more from Tony Sintes:
The method successfully alters the
value of pnt1, even though it is
passed by value; however, a swap of
pnt1 and pnt2 fails! This is the major
source of confusion. In the main()
method, pnt1 and pnt2 are nothing more
than object references. When you pass
pnt1 and pnt2 to the tricky() method,
Java passes the references by value
just like any other parameter. This
means the references passed to the
method are actually copies of the
original references. Figure 1 below
shows two references pointing to the
same object after Java passes an
object to a method.
(source: javaworld.com)
Conclusion or a long story short:
Java passes it parameters by value
"by value" is the only way in java to pass a parameter to a method
using methods from the object given as parameter will alter the object as the references point to the original objects. (if that method itself alters some values)
useful links:
http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
http://www.ibm.com/developerworks/java/library/j-passbyval/
http://www.ibm.com/developerworks/library/j-praxis/pr1.html
http://javadude.com/articles/passbyvalue.htm
Here is another article for the c# programming language
c# passes its arguments by value (by default)
private void swap(string a, string b) {
string tmp = a;
a = b;
b = tmp;
}
calling this version of swap will thus have no result:
string x = "foo";
string y = "bar";
swap(x, y);
"output:
x: foo
y: bar"
however, unlike java c# does give the developer the opportunity to pass parameters by reference, this is done by using the 'ref' keyword before the type of the parameter:
private void swap(ref string a, ref string b) {
string tmp = a;
a = b;
b = tmp;
}
this swap will change the value of the referenced parameter:
string x = "foo";
string y = "bar";
swap(x, y);
"output:
x: bar
y: foo"
c# also has a out keyword, and the difference between ref and out is a subtle one.
from msdn:
The caller of a method which takes an
out parameter is not required to
assign to the variable passed as the
out parameter prior to the call;
however, the callee is required to
assign to the out parameter before
returning.
and
In contrast ref parameters are
considered initially assigned by the
callee. As such, the callee is not
required to assign to the ref
parameter before use. Ref parameters
are passed both into and out of a
method.
a small pitfall is, like in java, that objects passed by value can still be changed using their inner methods
conclusion:
c# passes its parameters, by default, by value
but when needed parameters can also be passed by reference using the ref keyword
inner methods from a parameter passed by value will alter the object (if that method itself alters some values)
useful links:
http://msdn.microsoft.com/en-us/vcsharp/aa336814.aspx
http://www.c-sharpcorner.com/UploadFile/saragana/Willswapwork11162005012542AM/Willswapwork.aspx
http://en.csharp-online.net/Value_vs_Reference
Python uses pass-by-value, but since all such values are object references, the net effect is something akin to pass-by-reference. However, Python programmers think more about whether an object type is mutable or immutable. Mutable objects can be changed in-place (e.g., dictionaries, lists, user-defined objects), whereas immutable objects can't (e.g., integers, strings, tuples).
The following example shows a function that is passed two arguments, an immutable string, and a mutable list.
>>> def do_something(a, b):
... a = "Red"
... b.append("Blue")
...
>>> a = "Yellow"
>>> b = ["Black", "Burgundy"]
>>> do_something(a, b)
>>> print a, b
Yellow ['Black', 'Burgundy', 'Blue']
The line a = "Red" merely creates a local name, a, for the string value "Red" and has no effect on the passed-in argument (which is now hidden, as a must refer to the local name from then on). Assignment is not an in-place operation, regardless of whether the argument is mutable or immutable.
The b parameter is a reference to a mutable list object, and the .append() method performs an in-place extension of the list, tacking on the new "Blue" string value.
(Because string objects are immutable, they don't have any methods that support in-place modifications.)
Once the function returns, the re-assignment of a has had no effect, while the extension of b clearly shows pass-by-reference style call semantics.
As mentioned before, even if the argument for a is a mutable type, the re-assignment within the function is not an in-place operation, and so there would be no change to the passed argument's value:
>>> a = ["Purple", "Violet"]
>>> do_something(a, b)
>>> print a, b
['Purple', 'Violet'] ['Black', 'Burgundy', 'Blue', 'Blue']
If you didn't want your list modified by the called function, you would instead use the immutable tuple type (identified by the parentheses in the literal form, rather than square brackets), which does not support the in-place .append() method:
>>> a = "Yellow"
>>> b = ("Black", "Burgundy")
>>> do_something(a, b)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in do_something
AttributeError: 'tuple' object has no attribute 'append'
Since I haven't seen a Perl answer yet, I thought I'd write one.
Under the hood, Perl works effectively as pass-by-reference. Variables as function call arguments are passed referentially, constants are passed as read-only values, and results of expressions are passed as temporaries. The usual idioms to construct argument lists by list assignment from #_, or by shift tend to hide this from the user, giving the appearance of pass-by-value:
sub incr {
my ( $x ) = #_;
$x++;
}
my $value = 1;
incr($value);
say "Value is now $value";
This will print Value is now 1 because the $x++ has incremented the lexical variable declared within the incr() function, rather than the variable passed in. This pass-by-value style is usually what is wanted most of the time, as functions that modify their arguments are rare in Perl, and the style should be avoided.
However, if for some reason this behaviour is specifically desired, it can be achieved by operating directly on elements of the #_ array, because they will be aliases for variables passed into the function.
sub incr {
$_[0]++;
}
my $value = 1;
incr($value);
say "Value is now $value";
This time it will print Value is now 2, because the $_[0]++ expression incremented the actual $value variable. The way this works is that under the hood #_ is not a real array like most other arrays (such as would be obtained by my #array), but instead its elements are built directly out of the arguments passed to a function call. This allows you to construct pass-by-reference semantics if that would be required. Function call arguments that are plain variables are inserted as-is into this array, and constants or results of more complex expressions are inserted as read-only temporaries.
It is however exceedingly rare to do this in practice, because Perl supports reference values; that is, values that refer to other variables. Normally it is far clearer to construct a function that has an obvious side-effect on a variable, by passing in a reference to that variable. This is a clear indication to the reader at the callsite, that pass-by-reference semantics are in effect.
sub incr_ref {
my ( $ref ) = #_;
$$ref++;
}
my $value = 1;
incr(\$value);
say "Value is now $value";
Here the \ operator yields a reference in much the same way as the & address-of operator in C.
There's a good explanation here for .NET.
A lot of people are surprise that reference objects are actually passed by value (in both C# and Java). It's a copy of a stack address. This prevents a method from changing where the object actually points to, but still allows a method to change the values of the object. In C# its possible to pass a reference by reference, which means you can change where an actual object points to.
Don't forget there is also pass by name, and pass by value-result.
Pass by value-result is similar to pass by value, with the added aspect that the value is set in the original variable that was passed as the parameter. It can, to some extent, avoid interference with global variables. It is apparently better in partitioned memory, where a pass by reference could cause a page fault (Reference).
Pass by name means that the values are only calculated when they are actually used, rather than at the start of the procedure. Algol used pass-by-name, but an interesting side effect is that is it very difficult to write a swap procedure (Reference). Also, the expression passed by name is re-evaluated each time it is accessed, which can also have side effects.
Whatever you say as pass-by-value or pass-by-reference must be consistent across languages. The most common and consistent definition used across languages is that with pass-by-reference, you can pass a variable to a function "normally" (i.e. without explicitly taking address or anything like that), and the function can assign to (not mutate the contents of) the parameter inside the function and it will have the same effect as assigning to the variable in the calling scope.
From this view, the languages are grouped as follows; each group having the same passing semantics. If you think that two languages should not be put in the same group, I challenge you to come up with an example that distinguishes them.
The vast majority of languages including C, Java, Python, Ruby, JavaScript, Scheme, OCaml, Standard ML, Go, Objective-C, Smalltalk, etc. are all pass-by-value only. Passing a pointer value (some languages call it a "reference") does not count as pass by reference; we are only concerned about the thing passed, the pointer, not the thing pointed to.
Languages such as C++, C#, PHP are by default pass-by-value like the languages above, but functions can explicitly declare parameters to be pass-by-reference, using & or ref.
Perl is always pass-by-reference; however, in practice people almost always copy the values after getting it, thus using it in a pass-by-value way.
by value
is slower than by reference since the system has to copy the parameter
used for input only
by reference
faster since only a pointer is passed
used for input and output
can be very dangerous if used in conjunction with global variables
Concerning J, while there is only, AFAIK, passing by value, there is a form of passing by reference which enables moving a lot of data. You simply pass something known as a locale to a verb (or function). It can be an instance of a class or just a generic container.
spaceused=: [: 7!:5 <
exectime =: 6!:2
big_chunk_of_data =. i. 1000 1000 100
passbyvalue =: 3 : 0
$ y
''
)
locale =. cocreate''
big_chunk_of_data__locale =. big_chunk_of_data
passbyreference =: 3 : 0
l =. y
$ big_chunk_of_data__l
''
)
exectime 'passbyvalue big_chunk_of_data'
0.00205586720663967
exectime 'passbyreference locale'
8.57957102144893e_6
The obvious disadvantage is that you need to know the name of your variable in some way in the called function. But this technique can move a lot of data painlessly. That's why, while technically not pass by reference, I call it "pretty much that".
PHP is also pass by value.
<?php
class Holder {
private $value;
public function __construct($value) {
$this->value = $value;
}
public function getValue() {
return $this->value;
}
}
function swap($x, $y) {
$tmp = $x;
$x = $y;
$y = $tmp;
}
$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);
echo $a->getValue() . ", " . $b->getValue() . "\n";
Outputs:
a b
However in PHP4 objects were treated like primitives. Which means:
<?php
$myData = new Holder('this should be replaced');
function replaceWithGreeting($holder) {
$myData->setValue('hello');
}
replaceWithGreeting($myData);
echo $myData->getValue(); // Prints out "this should be replaced"
By default, ANSI/ISO C uses either--it depends on how you declare your function and its parameters.
If you declare your function parameters as pointers then the function will be pass-by-reference, and if you declare your function parameters as not-pointer variables then the function will be pass-by-value.
void swap(int *x, int *y); //< Declared as pass-by-reference.
void swap(int x, int y); //< Declared as pass-by-value (and probably doesn't do anything useful.)
You can run into problems if you create a function that returns a pointer to a non-static variable that was created within that function. The returned value of the following code would be undefined--there is no way to know if the memory space allocated to the temporary variable created in the function was overwritten or not.
float *FtoC(float temp)
{
float c;
c = (temp-32)*9/5;
return &c;
}
You could, however, return a reference to a static variable or a pointer that was passed in the parameter list.
float *FtoC(float *temp)
{
*temp = (*temp-32)*9/5;
return temp;
}