I'm creating own inspections based on Structural Replace.
For example I want to make inspection of transforming code like:
if (!$Map$.containsKey($key$)){
$Map$.put($key$, $value$);
}
and
if ($Map$.get($key$) == null){
$Map$.put($key$, $value$);
}
into
$Map$.putIfAbsent($key$, $value$);
But I don't want it to react on code like:
if (!$Map$.containsKey($key$)){
$Map$.put($key$, $value$);
}
else {
// any logic
}
I tried to use
if (!$Map$.containsKey($key$)){
$Map$.put($key$, $value$);
}
$else$
with option text "else" but it didn't work.
Is it possible? Also I have to make two different inspections with same replace result. Can we use multiple searh pattern?
UPDATE:
I tried replace next pattern
$Iterable$.forEach($value$ -> {
if ($condition$) {
$statement$;
}
});
into
$Iterable$.stream()
.filter($value$ -> $condition$)
.forEach($value$ -> $statement$);
But after replace I'm getting:
$Iterable$.stream()
.filter($value$ -> $condition$)
.forEach($value$ -> $statement$;);
Is it possible to remove ";" from replace result?
Use a search template like this:
if (!$Map$.containsKey($key$)){
$Map$.put($key$, $value$);
} else {
$statement$;
}
Edit variables and set the minimum and maximum count of statement to 0.
Using multiple search patterns for a single Structural Search Inspection is not possible at this time.
Related
I am not getting an efficient way to check below mentioned condition.
What I want to achieve is that-
There are some processes that need to be done if their corresponding boolean is true suggesting to start the process. So I want to check if a particular condition is done only if it should be started.
There are some boolean variables
var shouldStartProcessA
var shouldStartProcessB
var shouldStartProcessC
var isADone
var isBDone
var isCDone
if (shouldStartProcessA && shouldStartProcessB && shouldStartC) {
if (isADone && isBDone && isCDone) {
// Every process completed
}
}
if (shouldStartProcessA && shouldStartProcessB) {
if (isADone && isBDone) {
// Every process completed
}
}
if (shouldStartProcessA && shouldStartC) {
if (isADone && isCDone) {
// Every process completed
}
}
if (shouldStartProcessB && shouldStartC) {
if (isBDone && isCDone) {
// Every process completed
}
}
if (shouldStartProcessA) {
if (isADone) {
// Every process completed
}
}
if (shouldStartProcessB) {
if (isBDone) {
// Every process completed
}
}
if (shouldStartProcessC) {
if (isCDone) {
// Every process completed
}
}
This type of validating condition grows exponentially by introducing every other boolean. I am struggling to find a straightforward implementation to check these conditions.
Instead of doing things this way, I'd recommend a data structure that allows you to add tasks and check their state. There are a lot of ways to do that, but the basic idea is you can iterate over all the items and use functions like all to confirm they're all in the appropriate state. That way you don't have to hand-wire everything together
You could use a Map and add tasks to it, initially mapping them to false and setting that to true when they're completed. Or create a Set and add your tasks to that (I'm assuming you want one of each at most), and remove them / move them to a "done" list when they complete. That kind of idea. You could create an enum class to represent your tasks if you want, so each one is its own instance (e.g. Process.A, like having a dedicated, fixed variable) and you can easily use those in your logic
If you really want variables for each process, instead of a data structure, I'd still recommend rolling each pair into a single state, something like this:
enum class State {
UNUSED, PENDING, DONE
}
var processA = State.UNUSED
var processB = State.PENDING
// etc
// you can easily check them like this:
// create a list of all the variables you want to check - we're using references
// to the properties themselves (with the ::), not the current value!
val allProcesses = listOf(::processA, ::processB)
// now you have that collection, you can easily iterate over them all
// and work out what's what - we need to use get() to get the current values
val allFinished = allProcesses
.filterNot { it.get() == State.UNUSED } // ignore unused processes
.all { it.get() == State.DONE } // check ALL the required ones are DONE
You could write that check there as a single all condition, but the point is to show you you can be flexible with it, and build up your logic by filtering out the stuff you're not interested in, if you create a useful set of states
If you really do want to (or have to) stick with the current "pairs of variables" setup, you can do something similar:
// wiring them up again, creating a list of Pairs so we can iterate over them easily
val allProcesses = listOf(
::shouldStartProcessA to ::isADone,
::shouldStartProcessB to ::isBDone,
::shouldStartProcessC to ::isCDone
)
// gotta check 'em all - only returns true if that ALL meet the condition
val allComplete = allProcesses.all { (shouldStart, isDone) ->
// the get() syntax is awkward, but basically for everything we're checking
// if it either doesn't need to start, or it does but it's also done
!shouldStart.get() || (shouldStart.get() && isDone.get())
}
so adding new processes is just a case of adding their variables to the list of pairs, and they get included in the checking
You don't need the property reference stuff (::/.get()) if you create the lists right before you check them, but if you want to define them once in advance (and the property values can change after that) then that's how you'd do it. Otherwise you can just do the normal shouldStartProcessA to isADone etc, which is probably fine for most cases - I'm showing the reference stuff as a more general example for handling this kind of thing
I suppose, you should create two lists of Boolean and add variables consequently.
val list1 = listOf(shouldStartProcessA, shouldStartProcessB, shouldStartC)
val list2 = listOf(isADone, isBDone, isCDone)
Then iterate over both lists and check that items in corresponding positions have the same values.
var n = 0
for (i in list1.indices) {
if (list1[i] == list2[i]) {
n++
} else {
n = 0
break
}
}
if (n > 0) {
// Every process completed
}
Let me elaborate:
I need to be able to iterate over a list of objects. Each of the objects has a property which is a list, and I have to check if that list contains any elements that are not in another list.
When I tried to do it by using nested for loops, it kept giving me concurrent modification exceptions, so I tried to use an iterator, but now I'm stuck, since if I make an iterator based on the list of objects, I can't access the individual object's properties to then iterate over.
Here's some example code of what I was trying to accomplish:
for (preference in preferencesWithRestaurant) {
for (restaurantID in preference.restaurantIDs) {
// One method I tried using
preferencesWithRestaurant.removeIf{ !listOfIds.contains(restaurantID) }
/* alternate method I tried using
if (!listOfIds.contains(restaurantID)) {
preferencesWithRestaurant.remove(preference)
}
*/
}
}
If you can replace the value of preferencesWithRestaurant or store the result in another variable then you can filter it:
preferencesWithRestaurant = preferencesWithRestaurant.filter { preference ->
preference.restaurantIDs.all { it in listOfIds }
}
Depending on the exact type of preferencesWithRestaurant you may need to convert it to the proper type, e.g. invoke toMutableList() at the end.
If you prefer to modify preferencesWithRestaurant in-place, then you can use retainAll() (thanks #Tenfour04):
preferencesWithRestaurant.retainAll { preference ->
preference.restaurantIDs.all { it in listOfIds }
}
Alternatively, you can keep your original approach, but use a mutable iterator to remove an item while iterating:
val iter = preferencesWithRestaurant.listIterator()
for (preference in iter) {
for (restaurantID in preference.restaurantIDs) {
if (!listOfIds.contains(restaurantID)) {
iter.remove()
break
}
}
}
I'm operating on very large Kotlin sequence, I'm executing my logic on every step of the sequence and I never need to keep the whole sequence in memory.
Currently my code looks like this
hugeSequence
.filter { ... }
.map {...... }
.onEach {
callExpensiveOperation(it)
}
.toList() <- this feels wrong
The toList() at the bottom is the terminal operator, but I'm worried that Kotlin may try to create a huge list in memory, before realising that I'm not even assign the result value of that operation.
Is there any other terminal operator I can use just to trigger the sequence to start?
Use forEach instead of onEach. It is the terminal equivalent of onEach.
hugeSequence
.filter { ... }
.map {...... }
.forEach {
callExpensiveOperation(it)
}
I encountered the strangest thing.
Lets say I have a text file called "lines.txt". This file contains lines in key value pairs.
test:100
test1:200
test2:300
test3:400
If I read this file in Kotlin the list is not empty however the loop inside the output stream does not get called.
object App {
#JvmStatic
fun main(args: Array<String>) {
// file containing lines of text
val lines = Files.readAllLines(Paths.get("./hashes.txt"))
// not empty
println(lines.size)
// write back a modified version
PrintWriter(FileWriter(File("./lines2.txt"))).use { out -> {
// this doesn't get called
println(lines.size)
lines.forEach {
out.println(it.split(":")[0])
}
}
}
}
}
I don't understand why this is so if anyone can enlighten me that would be awesome.
The list is not empty. A single println(lines.size) will shown you that, because that println is never called.
You simply have one pair of curly braces too much.
change your code to
...
PrintWriter(FileWriter(File("./lines2.txt"))).use { out ->
// list is empty??
println(lines.size)
lines.forEach {
out.println(it.split(":")[0])
}
}
...
The reason is, that a lambda doesn't need its block in curly braces.
So don't write
out -> { ... }
just write
out -> ...
guenther already told you what is wrong with your code, but I think an explanation of what happened is missing.
Consider the following:
val x = { println("y") }
Will it print out y? No, the lamda is never invoked. You have to call x().
Let's take a look at what you did:
val x = { { println("y") } }
x()
Will it print out y? No, because you don't invoke the lambda that prints y.
To make things more clear, let's specify the types explicitely.
val x:() -> (() -> Unit) = { { println("y") } }
Now we can see that the first lambda invoked by x() returns a lambda as well so you would have to call x()() in order to invoke the returned lambda as well.
So using a second pair a curly braces is not just not optional but gives the code a whole new meaning.
But this means that there would be also another solution to your problem.
PrintWriter(FileWriter(File("./lines2.txt"))).use { out -> {
println(lines.size)
lines.forEach {
out.println(it.split(":")[0])
}
}() // <-- add braces here to invoke the lambda
}
So, you can either remove two brackets are add two more. Choice is yours.
Disclaimer: Removing two braces is the way to go. The other option is just to prove a point.
how would it be possible to bypass functions that are not existing in DM
such that the main code would still run? Try/catch does not seem to work, e..g
image doSomething(number a,number b)
{
try
{
whateverfunction(a,b)
}
catch
{
continue
}
}
number a,b
doSomething(a,b)
Also conditioning wont work, e.g..
image doSomething(number a,number b)
{
if(doesfunctionexist("whateverfunction"))
{
whateverfunction(a,b)
}
}
number a,b
doSomething(a,b)
thanks in advance!
As "unknown" commands are caught by the script-interpreter, there is no easy way to do this. However, you can construct a workaround by using ExecuteScriptCommand().
There is an example tutorial to be found in this e-book, but in short, you want to do something like the following:
String scriptCallStr = "beep();\n"
scriptCallStr = "MyUnsaveFunctionCall();\n"
number exitVal
Try { exitVal = ExecuteScriptString(scriptCallStr ); }
Catch { exitVal = -1; break; }
if ( -1 == exitVal )
{
OKDialog("Sorry, couldn't do:\n" + scriptCallStr )
}
else
{
OKDialog( "All worked. Exit value: " + exitVal )
}
This works nicely and easy for simple commands and if your task is only to "verify" that a script could run.
It becomes clumsy, when you need to pass around parameters. But even then there are ways to do so. (The 'outer' script could create an object and pass the object-ID per string. Similarly, the 'inner' script can do the same and return the script-object ID as exit-value.)
Note: You can of course also put doesfunctionexist inside the test-script, if you do only want to have a "safe test", but don't actually want to execute the command.
Depending on what you need there might also be another workaround solution: Wrapper-functions in a library. This can be useful if you want to run the same script on different PCs with some of which having the functionality - most likely some microscope - while others don't.
You can make your main-script use wrapper methods and then you install different versions of the wrapper method script scripts as libraries.
void My_SpecialFunction( )
{
SpecialFunction() // use this line on PCs which have the SpecialFunction()
DoNothing() // use alternative line on PCs which don't have the SpecialFunction()
}
My_SpecialFunction( )
I have used this in the past where the same functionality (-stage movement-) required different commands on different machines.