I am reading someone else sql and his code was like this
There is view called user_v with column path as Array
select * from user_v where 'USER_TYPE'=path[2]
can't i use
path[2] = 'USER_TYPE'
This is a precaution taken by some programmers in languages where assignment and comparison can be easily confused, such as C or PHP, where the following statement looks innocent:
if ( $foo = 1 )
but it is actually assigning 1 to $foo, and the if will always evaluate to true (in PHP, at least, where 1 is true). What was meant was if ( $foo == 1 ).
If you reverse the arguments, the error becomes obvious sooner:
if ( 1 = $foo ) # SYNTAX ERROR
if ( 1 == $foo ) # Desired behaviour
This is sometimes known as "yoda coding", and is in the coding standards of Wordpress, for example.
See also: Why put the constant before the variable in a comparison?
In SQL, there is less chance of such a muddle, since although = can mean either assignment or comparison, there are rarely situations where a typo would select the wrong meaning.
However, if the coding standards for every other language used by a project mandate it, it would make sense to reinforce the habit by also using it in SQL, since I can't think of a specific reason not to write it that way.
There is no difference at all.
It's psychology.
You would want to read someone else's code out laud and say:
Where my column equals 2.
When you read:
Where 2 equals my column
you have to stop for a while, return, explain it to yourself.
We maintain all of these rules that seem rubish at first glance just to make other people lives easier.
Related
I am using a MixHash to combine two Hashes with the Bag add (+) operator. This seems to work - but ... I am a bit surprised that the result of the union needs to be re-coerced back to a MixHash.
My guess is that the Bag add (+) infix operator coerces everything to a Bag first and returns the result as a Bag. This may be risky for me as some of my weights are negative (thus the Mix in the first place). Will this properly add negative weights?
Alternatively, is there a Mix add (+) operator?
my MixHash $dim-mix;
for ... {
my $add-mix = $!dims.MixHash;
$dim-mix = $dim-mix ?? ( $dim-mix (+) $add-mix ).MixHash !! $add-mix;
}
dd $dim-mix;
Now I look at this paraphrased code, perhaps there is some formulation of ternary ?? !! that can avoid spelling out $dim-mix in the test since already on the left?
Many thanks for any advice!
my $add-mix = (foo => 0.22, bar => -0.1).Mix;
my $dim-mix;
for ^5 {
$dim-mix (+)= $add-mix;
}
dd $dim-mix; # Mix $dim-mix = ("foo"=>1.1,"bar"=>-0.5).Mix
Obviously I've not used a MixHash, but you can sort that out if you need to after the loop.
(And of course you might be thinking "but isn't a Mix immutable?" It is -- but you have to distinguish variables and values. $dim-mix is a variable, a Scalar variable. Even if you type it -- my Mix $dim-mix; it's still a Scalar variable holding a Mix value. You can always assign to a Scalar.)
I'm starting to get a routine for questions like this where I don't know what's going on but I think I ought to be able to figure it out. Here was my process:
I got your code to run to see what it did. I tried to simplify the ternary. Hmm.
I turned to the doc. There was the doc page for (+). That called it "Baggy addition". That was worrisome given that a Bag only holds (positive) integers.
I turned to the source. I fired off a search of the rakudo sources for "Baggy addition". One result. I focused on the multi with (Mixy:D $a, QuantHash:D $b) signature. This showed me that the result should stay Mixy, i.e. the doc's implication it would or could go Baggy is a red herring.
I returned to the code and started wondering what I could do. When I initially tried to use (+)= to simplify the main assignment the compiler complained expected MixHash but got Mix. I tried a half dozen things that didn't work then just changed the MixHash constraint on $dim-mix to Mixy and it worked.
Then I thought through what was going on and realized that almost all the types were getting in the way of P6 just doing the right thing.
You can add some types back in if you really need them.
(But do you really need them? When types are absolutely necessary they're great. Otherwise, imo, think twice, and then twice again, before introducing them. They can easily make code harder to read, reason about, compose, and slower.)
(Of course there are occasions on which they're not strictly necessary but do really help overall. Imo, as with all things, keep it simple at first and only complexify if you see clear benefits for a particular line of code.)
The large majority of SonarLint rules that I've come across in Java seemed plausible and justified. However, ever since I've started using SonarLint for VB.NET, I've come across several rules that left me questioning their usefulness or even whether or not they are working correctly.
I'd like to know if this is simply a problem of me using some VB.NET constructs in a suboptimal way or whether the rule really is flawed.
(Apologies if this question is a little longer. I didn't know if I should create a separate question for each individual rule.)
The following rules I found to leave some cases unconsidered that would actually turn up as false-positives:
S1871: Two branches in the same conditional structure should not have exactly the same implementation
I found this one to bring up a lot of false-positives for me, because sometimes the order in which the conditions are checked actually does matter. Take the following pseudo code as example:
If conditionA() Then
doSomething()
ElseIf conditionB() AndAlso conditionC() Then
doSomethingElse()
ElseIf conditionD() OrElse conditionE() Then
doYetAnotherThing()
'... feel free to have even more cases in between here
Else Then
doSomething() 'Non-compliant
End If
If I wanted to follow this Sonar rule and still make the code behave the same way, I'd have to add the negated version of each ElseIf-condition to the first If-condition.
Another example would be the following switch:
Select Case i
Case 0 To 40
value = 0
Case 41 To 60
value = 1
Case 61 To 80
value = 3
Case 81 To 100
value = 5
Case Else
value = 0 'Non-compliant
There shouldn't be anything wrong with having that last case in a switch. True, I could have initialized value beforehand to 0 and ignored that last case, but then I'd have one more assignment operation than necessary. And the Java ruleset has conditioned me to always put a default case in every switch.
S1764: Identical expressions should not be used on both sides of a binary operator
This rule does not seem to take into account that some functions may return different values every time you call them, for instance collections where accessing an element removes it from the collection:
stack.Push(stack.Pop() / stack.Pop()) 'Non-compliant
I understand if this is too much of an edge case to make special exceptions for it, though.
The following rules I am not actually sure about:
S3385: "Exit" statements should not be used
While I agree that Return is more readable than Exit Sub, is it really bad to use a single Exit For to break out of a For or a For Each loop? The SonarLint rule for Java permits the use of a single break; in a loop before flagging it as an issue. Is there a reason why the default in VB.NET is more strict in that regard? Or is the rule built on the assumption that you can solve nearly all your loop problems with LINQ extension methods and lambdas?
S2374: Signed types should be preferred to unsigned ones
This rule basically states that unsigned types should not be used at all because they "have different arithmetic operators than signed ones - operators that few developers understand". In my code I am only using UInteger for ID values (because I don't need negative values and a Long would be a waste of memory in my case). They are stored in List(Of UInteger) and only ever compared to other UIntegers. Is this rule even relevant to my case (are comparisons part of these "arithmetic operators" mentioned by the rule) and what exactly would be the pitfall? And if not, wouldn't it be better to make that rule apply to arithmetic operations involving unsigned types, rather than their declaration?
S2355: Array literals should be used instead of array creation expressions
Maybe I don't know VB.NET well enough, but how exactly would I satisfy this rule in the following case where I want to create a fixed-size array where the initialization length is only known at runtime? Is this a false-positive?
Dim myObjects As Object() = New Object(someOtherList.Count - 3) {} 'Non-compliant
Sure, I could probably just use a List(Of Object). But I am curious anyway.
Thanks for raising these points. Note that not all rules apply every time. There are cases when we need to balance between false positives/false negatives/real cases. For example with identical expressions on both sides of an operator rule. Is it a bug to have the same operands? No it's not. If it was, then the compiler would report it. Is it a bad smell, is it usually a mistake? Yes in many cases. See this for example in Roslyn. Should we tune this rule to exclude some cases? Yes we should, there's nothing wrong with 2 << 2. So there's a lot of balancing that needs to happen, and we try to settle for an implementation that brings the most value for the users.
For the points you raised:
Two branches in the same conditional structure should not have exactly the same implementation
This rule generally states that having two blocks of code match exactly is a bad sign. Copy-pasted code should be avoided for many reasons, for example if you need to fix the code in one place, you'll need to fix it in the other too. You're right that adding negated conditions would be a mess, but if you extract each condition into its own method (and call the negated methods inside them) with proper names, then it would probably improves the readability of your code.
For the Select Case, again, copy pasted code is always a bad sign. In this case you could do this:
Select Case i
...
Case 0 To 40
Case Else
value = 0 ' Compliant
End Select
Or simply remove the 0-40 case.
Identical expressions should not be used on both sides of a binary operator
I think this is a corner case. See the first paragraph of the answer.
"Exit" statements should not be used
It's almost always true that by choosing another type of loop, or changing the stop condition, you can get away without using any "Exit" statements. It's good practice to have a single exit point from loops.
Signed types should be preferred to unsigned ones
This is a legacy rule from SonarQube VB.NET, and I agree with you that it shouldn't be enabled by default in SonarLint. I created the following ticket in our JIRA: https://jira.sonarsource.com/browse/SLVS-1074
Array literals should be used instead of array creation expressions
Yes, it seems to be a false positive, we shouldn't report on array creations when the size is explicitly specified. https://jira.sonarsource.com/browse/SLVS-1075
In VB.NET, there's no == operator for comparison, so the = operator serves that purpose as well as assignment. I have a function, and I want it to return the boolean result of a comparison, without storing that result in a variable:
Private Function foo() As Boolean
Dim bar As Integer = 1
Return bar = 2
End Function
Returns: False
OK, but what's the value of bar?
Private Function foo() As KeyValuePair(Of Boolean, Integer)
Dim bar As Integer = 1
Return New KeyValuePair(Of Boolean, Integer)(bar = 2, bar)
End Function
Returns: False, 1
It looks like = will perform a comparison when the statement context demands it, but is this guaranteed? That is, can I be sure that bar will never be set to 2 in this situation?
Also, I know that VB.NET doesn't allow chained inline assignments, which may be for the best. Does this odd = behavior cause any other quirks I should be aware of?
You cannot do in-line assignments in VB, Assignment is an explicit statement:
[Let] <<target-reference>> = <<value-expression>>
The Let is optional and implicit, and hardly ever used anymore. The general rule that you can use to distinguish the [Let] command from equality testing is that for Let, no other keyword may come before the target-reference in the statement. AFAIK, in all cases of = as equality testing, there is one or more other keywords that precede it in the statement.
In your first example, the keyword Return precedes your =, so it's an equality test, and not an assignment.
In your first example you can do either:
Return 2
or
bar = 2
Return bar
As for your question "OK, but what's the value of bar?", bar still equals one.
= in VB cause no quirks. It works exactly as documented, and it always has (including its predecessor, BASIC back to 1968).
If you are starting to code in VB (coming from a language like C#), you should start getting used to the peculiar VB way of doing things; which is based on the idea: as simple and intuitive for the programmer as possible. "If assignation and comparison happen always in different contexts, why not using the same operator and let the context define its exact meaning?" -> VB-way of seeing things. "No, different realities have to be accounted for by different operators. End of the discussion" -> C#-way. :)
Is this reliable? Can you blindly trust on these not-always-clear-for-a-programmer bits? Sure, VB.NET peculiarities are highly-reliable and trustworthy. You can always use = (or Is on some contexts, but VS would tell you) and be completely sure that the code will do what is expected. But the question is: are you sure that you write exactly what you want?
This last question is what, perhaps, is more criticable of VB and what might give some problems to programmers from other languages: the higher the flexibility, the more likely is that you make an error; mainly if you are used to a different format.
Regarding the chained inline assignments, I honestly don't see its true utility (and never use them in C#). Regarding other differences with respect to C#, there are plenty of them; in some cases, I think that the C# approach is better; other times, the VB.NET one. On readability/length of code, I can refer to the With Statement I have always found somehow useful which is not present in C#.
One way to have 100% sure that the expression will be evaluated as an boolean expression is to use ()
e.g
Dim a = 2
Return (a = 1)
Since you cannot set a value to a variable wihtin the parenthesis.
What i want to say is: on an return statament for example you cant assing a value to a variable so, even if you use
a = 1
The compilator knows that this expression only can be an boolean expression.
The same to the if statament and so on..
Heh back in QB45 days we used to exploit the fact that "True" was the numeric value -1. So you would see code like x = 1 - x * (x < 6) (translation: increment x, but reset to 1 when it gets to 6)
In algebra if I make the statement x + y = 3, the variables I used will hold the values either 2 and 1 or 1 and 2. I know that assignment in programming is not the same thing, but I got to wondering. If I wanted to represent the value of, say, a quantumly weird particle, I would want my variable to have two values at the same time and to have it resolve into one or the other later. Or maybe I'm just dreaming?
Is it possible to say something like i = 3 or 2;?
This is one of the features planned for Perl 6 (junctions), with syntax that should look like my $a = 1|2|3;
If ever implemented, it would work intuitively, like $a==1 being true at the same time as $a==2. Also, for example, $a+1 would give you a value of 2|3|4.
This feature is actually available in Perl5 as well through Perl6::Junction and Quantum::Superpositions modules, but without the syntax sugar (through 'functions' all and any).
At least for comparison (b < any(1,2,3)) it was also available in Microsoft Cω experimental language, however it was not documented anywhere (I just tried it when I was looking at Cω and it just worked).
You can't do this with native types, but there's nothing stopping you from creating a variable object (presuming you are using an OO language) which has a range of values or even a probability density function rather than an actual value.
You will also need to define all the mathematical operators between your variables and your variables and native scalars. Same goes for the equality and assignment operators.
numpy arrays do something similar for vectors and matrices.
That's also the kind of thing you can do in Prolog. You define rules that constraint your variables and then let Prolog resolve them ...
It takes some time to get used to it, but it is wonderful for certain problems once you know how to use it ...
Damien Conways Quantum::Superpositions might do what you want,
https://metacpan.org/pod/Quantum::Superpositions
You might need your crack-pipe however.
What you're asking seems to be how to implement a Fuzzy Logic system. These have been around for some time and you can undoubtedly pick up a library for the common programming languages quite easily.
You could use a struct and handle the operations manualy. Otherwise, no a variable only has 1 value at a time.
A variable is nothing more than an address into memory. That means a variable describes exactly one place in memory (length depending on the type). So as long as we have no "quantum memory" (and we dont have it, and it doesnt look like we will have it in near future), the answer is a NO.
If you want to program and to modell this behaviour, your way would be to use a an array (with length equal to the number of max. multiple values). With this comes the increased runtime, hence the computations must be done on each of the values (e.g. x+y, must compute with 2 different values x1+y1, x2+y2, x1+y2 and x2+y1).
In Perl , you can .
If you use Scalar::Util , you can have a var take 2 values . One if it's used in string context , and another if it's used in a numerical context .
In this question, a user commented to never use the With block in VB. Why?
"Never" is a strong word.
I think it fine as long as you don't abuse it (like nesting)
IMHO - this is better:
With MyCommand.Parameters
.Count = 1
.Item(0).ParameterName = "#baz"
.Item(0).Value = fuz
End With
Than:
MyCommand.Parameters.Count = 1
MyCommand.Parameters.Item(0).ParameterName = "#baz"
MyCommand.Parameters.Item(0).Value = fuz
There is nothing wrong about the With keyword. It's true that it may reduce readibility when nested but the solution is simply don't use nested With.
There may be namespace problems in Delphi, which doesn't enforce a leading dot but that issue simply doesn't exist in VB.NET so the people that are posting rants about Delphi are losing their time in this question.
I think the real reason many people don't like the With keyword is that is not included in C* languages and many programmers automatically think that every feature not included in his/her favourite language is bad.
It's just not helpful compared to other options.
If you really miss it you can create a one or two character alias for your object instead. The alias only takes one line to setup, rather than two for the With block (With + End With lines).
The alias also gives you a quick mouse-over reference for the type of the variable. It provides a hook for the IDE to help you jump back to the top of the block if you want (though if the block is that large you have other problems). It can be passed as an argument to functions. And you can use it to reference an index property.
So we have an alternative that gives more function with less code.
Also see this question:
Why is the with() construct not included in C#, when it is really cool in VB.NET?
The with keyword is only sideswiped in a passing reference here in an hilarious article by the wonderful Verity Stob, but it's worth it for the vitriol: See the paragraph that starts
While we are on identifier confusion. The with keyword...
Worth reading the entire article!
The With keyword also provides another benefit - the object(s) in the With statement only need to be "qualified" once, which can improve performance. Check out the information on MSDN here:
http://msdn.microsoft.com/en-us/library/wc500chb(VS.80).aspx
So by all means, use it.