I was wondering if there is a simpler or shorter way to write repetitive conditions like x == 1 && y == 1 && z == 1?
When it is (exactly) repeated code, you should consider to extract the statement into a method and give a meaningfull name, which you know from the context where it is used. This makes the requirement (reading the code) easier to understand, at the point where it is used. And it makes it also easier to spot the it is always the same condition.
if (conditionName(x, y, z)) {
}
fun boolean conditionName(int x, int y, int z) {
return x == 1 && y == 1 && z == 1;
}
I cannot think of a shorter statement for the condition, but a method extraction will improve your code readability, which should be your overall goal.
You could consider using predicates using all. For example:
listOf(x, y, z).all {it == 1}
This will return true when x==1, y==1, and z==1.
If the goal is to shorten what you want, there's not much legroom as your boolean expression is already very concise. Some of the other answers have illustrated how to make what you want more readable, however.
You can make a convenience function for this kind of repeated code (or if you just need it to be more readable, or safer to edit):
fun <T> T.allEqual(vararg items: T) = items.all { it == this }
// or you could make the receiver the first parameter instead, this is just
// more explicit about which item is the value being compared against
1.allEqual(x, y, z)
But no, there isn't any other shorthand built into the language as far as I'm aware - conditions like x == 1 chained with boolean operators are about as simple as it can get! If you want to check multiple things without repeating yourself, any and all make that easy, while being flexible for all kinds of situations, and allowing the user to put together the functionality they need with those more general functions.
If you specifically want a version of all that does a simple comparison to a single value, and doesn't require creating an iterable like listOf, you have to write your own with those tools (which is basically what I've done). It's up to you if you think it's worth it!
If it makes sense you could hold those variables in a class
data class XYZ(
val x: Int,
val y: Int,
val z: Int)
And compare your instance with XYZ(1, 1, 1);
Or if it's just those three variables, you could write
if (Triple(x, y, z) == Triple(1, 1, 1))
val x = 1
val y = 1
var z = 1
println("$x$y$z" == "111") // prints 'true'
z = 2
println("$x$y$z" == "111") // prints 'false'
Related
I'm looking for a pythonic way for the code below.
Function foo() may return an int or "None" and in that case "None" should be replaced by a default value.
I doubt that this can't be simplified and reduced to a one-liner, I just don't know how to do it ^^
def foo() -> int:
# code
x = foo()
x = 0 if x is None else x
That is plenty Pythonic and concise (2 lines). The only way to reduce it to 1 line is to use the walrus operator:
x = 0 if (x := foo()) is None else x
# ^ assigns foo() to x and ^ x is reused here
#^but x is ultimately reassigned here
you can use or operator. If the first argument resolves to False, second one is assigned. Example:
x = foo() or default_value
The issue with that is, if foo() will return 0 for example, default value will be assigned
I want to know if the code I wrote can be shortened further, I was practicing and I came up to a task which asks you to return a boolean value, this is what the question says:
Given two strings, return True if either of the strings appears at the
very end of the other string, ignoring upper/lower case differences
(in other words, the computation should not be "case sensitive").
Note: s.lower() returns the lowercase version of a string.
def end_other(a, b):
x = len(b)
n = a[-x:]
y = len(a)
m = b[-y:]
if b.lower() == n.lower() or a.lower() == m.lower() :
return True
else:
return False
The Code is working properly but I wondered if it can be shortened more so it looks good.
You can write it like this:
def end_other(a, b):
n = a[-len(b):]
m = b[-len(a):]
return b.lower() == n.lower() or a.lower == m.lower()
I removed variables x and y because they are used just one time and then I also remove the if-else statement because it's unnecessary, in fact you can just return the result of the comparison instead of checking it's result and returning it a second time.
in designing an algebraic equation modelling system, I had this dilemma: we cannot associate properties to a number, if I turn the number to a table with a field "value" for example, I can overload arithmetic operators, but not the logic operator since that only works when both operands have same metatable, while my users will compare "x" with numbers frequently.
For example, here is a minimal equation solver system:
x = 0
y = 0
eq1 = {function() return 2*x + 3*y end, rhs = 1 }
eq2 = {function() return 3*x + 2*y end, rhs = 2 }
p = {{x,y},{eq1, eq2}}
solve(p)
The "solve()" will process table "p" to get all coefficients of the equation system and rhs. However, it is essential, a user can associate properties to "x" and "y", for example, lower bound, upper bound. I tries using table,
x = {val=0, lb=0, ub=3}
y = {val=1,lb=3,ub=5}
....
and write metamethods for "x" and "y" such that arithmetic operating will act on x.val and y.val. However, in a scripting environment, we also need to compare "x" with numbers, i.e., "if x>0 then ...". And I stuck here. An ugly solution is to ask users to use x.val, y.val everywhere in modelling the equation and scripting. Does anyone here has similar need to associate properties to a number, and the number can still be used in arithmetic/logic operations?
Something like this could work:
x = {val = 10}
mt = {}
mt.__lt = function (op1, op2)
if (type(op1) == 'table') then a = op1.val else a = op1 end
if (type(op2) == 'table') then b = op2.val else b = op2 end
return a < b
end
setmetatable(x, mt)
print(x < 5) -- prints false
print(x < 15) -- prints true
print(x < x) -- prints false
print(5 < x) -- prints true
Of course, you would write similar methods for the other operators (__add, __mul, __eq and so on).
If you'd rather not use type()/reflection, you can use an even dirtier trick that takes advantage of the fact that unary minus is well, unary:
mt = {}
mt.__unm = function (num) return -(num.val) end
mt.__lt = function (a, b) return -(-a) < -(-b) end
This is rather simple if you have access to the debug library, do you?
debug.setmetatable(0, meta)
meta will be the metatable of ALL numbers. This will solve your logical overloading problem.
However if you would prefer assigning properties to numbers, there is a way you could do this, I wrote a quick example on how one would do so:
local number_props = {
{val="hi"},
{val="hi2"}
}
debug.setmetatable(0,{__index=function(self,k)return number_props[self][k]end})
print((1).val, (2).val)
Can you have multiple evaluations in your WHEN clause?
For example is there a way to do something like this:
when (x == "Open" and y == "Ready") $ do...
I can get a single condition to work, but what if I need both to be true?
How about something like
when (x == "Open" && y == "Ready") $ do
...
&& is just a normal infix operator defined as
True && a = a
False && _ = False
Notice that with laziness this has exactly the same short circuiting properties we get in other languages!
On a totally separate note, instead of using strings to represent different states the Haskell-ish way would be to define your own type
data StateOfFoo = Ready
| Open
| Closed
| ...
deriving(Eq)
and then use x == Open && y == Ready for example. This way you make it clear in the types what you expect x and y to be.
protected int xMethod (Integer a, Integer b) {
if (a<b)
return 1
else if (a>b)
return 2
else
return 3
}
I wonder if there is some way of rewriting above method differently in groovy? as now is very Java style.
It seems that the function just needs to return 3 different values depending on whether a is less than, equal to, or greater than b. There is already an operator in Groovy that does this:
a <=> b
The return values are -1, 0 and 1. Perhaps the best thing to do is refactor the code to use this operator instead of xMethod, if that is possible.
Of course, if the precise values 1, 2 and 3 are important and not just 3 distinct values then you can't do this.
Just to expand on Mark's answer:
protected int xMethod (Integer a, Integer b) {
switch ( a <=> b ) {
case -1: 1; break
case 1: 2; break
case 0: 3; break
}
}
However, you have to question whether this method has any value. If the caller can be changed to accept -1, 0, 1 then the method has no reason to exist.
How about:
return (a <=> b) + 2
If you remove the two occurrences of Integer from the signature, you can call the method with any parameters for which < is defined.
E.g.
assert x.xMethod(1, 2)==1
assert x.xMethod("2", "1")==2
assert x.xMethod(2.0, 2.0)==3