I would like in my groovy script to dump all variables and display all values.
I would like to do it dynamically because I would like to surround all my huge groovies by a try/catch. In catch part I want to dump all variables state with the stacktrace. The code should be generic to all groovies.
The problem is that this.getBinding().getVariables() doesn't return the correct variable state.
I've made a small script to illustrate the situation:
def test1 = 1;
test1 = 2;
int test2 = 1;
test2 = 2;
test3 = 1;
test3 = 2;
def errLog=new File("c:/temp/groovy_debug.txt");
errLog.append("--------------------------------------------------------" + "\n");
errLog.append(" Context ["+getBinding().getVariables()+" ] \n");
errLog.append("--------" + "\n") ;
after the execution I get a very strange result
--------------------------------------------------------
Context [[[creationStackTrace= <not available>], test1:null, errLog:null, test2:null, test3:2] ]
--------
it means that the declared variables are always reported as null or as first assignment, but for not typed variables it get the last value.
I would like to get the last situation for all variables (value=2).
Is it possible to get them?
Tim Yates' answer illustrates why you're having difficulty accessing the non-global variables. For simple cases like yours, where you just have assignments and declarations, you can use a visitor to collect the results, like this
import org.codehaus.groovy.ast.expr.*
import org.codehaus.groovy.ast.stmt.*
import org.codehaus.groovy.ast.*
import org.codehaus.groovy.control.*
import org.codehaus.groovy.classgen.*
import java.security.CodeSource
def scriptText = '''
def test1 = 1;
test1 = 2;
int test2 = 1;
test2 = 2;
test3 = 1;
test3 = 2;
'''
class VariableVisitor extends ClassCodeVisitorSupport {
def vars = [:]
void visitExpressionStatement(ExpressionStatement statement) {
if (statement.expression instanceof BinaryExpression)
vars.put(statement.expression.leftExpression.name, statement.expression.rightExpression.value)
super.visitExpressionStatement(statement)
}
void visitReturnStatement(ReturnStatement statement) {
if (statement.expression instanceof BinaryExpression)
vars.put(statement.expression.leftExpression.name, statement.expression.rightExpression.value)
super.visitReturnStatement(statement)
}
protected SourceUnit getSourceUnit() {
return source;
}
}
class CustomSourceOperation extends CompilationUnit.PrimaryClassNodeOperation {
CodeVisitorSupport visitor
void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException {
classNode.visitContents(visitor)
}
}
class MyClassLoader extends GroovyClassLoader {
CodeVisitorSupport visitor
protected CompilationUnit createCompilationUnit(CompilerConfiguration config, CodeSource source) {
CompilationUnit cu = super.createCompilationUnit(config, source)
cu.addPhaseOperation(new CustomSourceOperation(visitor: visitor), Phases.CLASS_GENERATION)
return cu
}
}
def visitor = new VariableVisitor()
def myCL = new MyClassLoader(visitor: visitor)
def script = myCL.parseClass(scriptText)
assert visitor.vars == ["test1":2, "test2":2, "test3":2]
However, if your script has more complicated stuff going on (like conditional assignments), you'll need something more sophisticated. You'd need to actually run the script and collect the results.
Related
Using Jetpack Compose on Android.
I have a test, that simulates a selection of several Text composable in a Column.
The selection starts by a long-press on the first item and then moves down over more Text composables and stop well inside the Column.
Usually the test should run unattended and fast.
But I want to be able to show the selection process in real time (for demonstration purposes and also to see, if it works like it's designed, e.g. at the beginning I forgot that I have to wait some time after the down()).
The first Text composable in the column is also used to find the element (->anchor), and the parent is the Column which is used to perform the move.
This is the function that performs the selection:
val duration = 3000L
val durationLongPress = 1000L
fun selectVertical(anchor: SemanticsNodeInteraction, parent: SemanticsNodeInteraction) {
anchor.performTouchInput {
down(center)
}
clock.advanceTimeBy(durationLongPress)
// the time jumps here, but the selection of the first word is visible
val nSteps = 100
val timeStep = (duration-durationLongPress)/nSteps
parent.performTouchInput {
moveTo(topCenter)
val step = (bottomCenter-topCenter)*0.8f/ nSteps.toFloat()
repeat(nSteps) {
moveBy(step, timeStep)
}
up()
}
}
this is the composable:
#Composable
fun SelectableText() {
val text = """
|Line
|Line start selecting here and swipe over the empty lines
|Line or select a word and extend it over the empty lines
|Line
|
|
|
|Line
|Line
|Line
|Line
""".trimMargin()
Column {
SelectionContainer {
Column {
Text("simple")
Text(text = text) // works
}
}
SelectionContainer {
Column {
Text("crash")
text.lines().forEach {
Text(text = it)
}
}
}
SelectionContainer {
Column {
Text("space")
text.lines().forEach {
// empty lines replaced by a space works
Text(text = if (it == "") " " else it)
}
}
}
}
}
a test goes like this:
#Test
fun works_simple() {
val anchor = test.onNodeWithText("simple")
val textNode = anchor.onParent()
textNode.printToLog("simple")
controlTime(duration) {
selectVertical(anchor, textNode)
}
}
controlTime is the part that does not work. I don't add it's code here to keep the solution open.
I tried to disable the autoAdvance on the virtual test clock and stepping the time in a loop in a coroutine.
When I step the time in 1ms steps and add a delay(1) each, the wait is correct, but I don't see the selection expanding (I want at least see the steps). Instead I see the selection of the first word, then nothing until the end of the move and then the end result.
I also divided the move into smaller steps e.g. 10 or 100, but it's still not showing the result.
ok, I found the solution myself when sleeping... the "sleeping" brain is obviously working on unsolved problems (well, I know this already).
The key is, to do each move that should be visible in it's own performXXX. I think, the result is only propagated to the UI, when the code block is finished, which makes sense for a test.
parent.performTouchInput {
inRealTime("moveBy($step, $timeStep)", timeStep) {
moveBy(step)
}
}
I couldn't find a way to determine the duration of a so called "frame", so I advance either the virtual or the real clock, depending on which is lagging until both reach the target time. This can probably be optimized to jump both clocks in one step. I'll investigate that later.
It's interesting, that even 100 steps don't show a smooth selection move.
Instead, there are still only a few steps, even when the step time is increased.
Btw. this purpose of this code is to show a crash in SelectionContainer, when it encounters an empty Text("") composable for a bug report I created. I will provide it on the issue tracker, but I also want to have the test in our app development, to see, when it's solved and to avoid a library that doesn't work. Sometimes we encounter regressions in libs, e.g. if the fix has a bug.
This is the complete test code:
package com.example.myapplication
import android.util.Log
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.test.*
import androidx.compose.ui.test.junit4.ComposeContentTestRule
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import kotlinx.coroutines.*
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Before
import org.junit.Rule
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
#RunWith(AndroidJUnit4::class)
class CrashTest {
val duration = 3000L
val durationLongPress = 1000L
#Composable
fun SelectableText() {
val text = """
|Line
|Line start selecting here and swipe over the empty lines
|Line or select a word and extend it over the empty lines
|Line
|
|
|
|Line
|Line
|Line
|Line
""".trimMargin()
Column {
SelectionContainer {
Column {
Text("simple")
Text(text = text) // works
}
}
SelectionContainer {
Column {
Text("crash")
text.lines().forEach {
Text(text = it)
}
}
}
SelectionContainer {
Column {
Text("space")
text.lines().forEach {
// empty lines replaced by a space works
Text(text = if (it == "") " " else it)
}
}
}
}
}
#Rule
#JvmField
var test: ComposeContentTestRule = createComposeRule()
#Before
fun setUp() {
test.setContent { SelectableText() }
test.onRoot().printToLog("root")
}
val clock get() = test.mainClock
fun inRealTime(what: String? = null, duration: Long = 0, todo: () -> Unit) {
clock.autoAdvance = false
what?.let { Log.d("%%%%%%%%%%", it) }
val startVirt = clock.currentTime
val startReal = System.currentTimeMillis()
todo()
while (true) {
val virt = clock.currentTime - startVirt
val real = System.currentTimeMillis() - startReal
Log.d("..........", "virt: $virt real: $real")
if (virt > real)
Thread.sleep(1)
else
clock.advanceTimeByFrame()
if ((virt > duration) and (real > duration))
break
}
clock.autoAdvance = true
}
fun selectVertical(anchor: SemanticsNodeInteraction, parent: SemanticsNodeInteraction) {
inRealTime("down(center)", durationLongPress) {
anchor.performTouchInput {
down(center)
}
}
val nSteps = 100
val timeStep = (duration-durationLongPress)/nSteps
Log.d("----------", "timeStep = $timeStep")
var step = Offset(1f,1f)
parent.performTouchInput {
step = (bottomCenter-topCenter)*0.8f/ nSteps.toFloat()
}
repeat(nSteps) {
parent.performTouchInput {
inRealTime("moveBy($step, $timeStep)", timeStep) {
moveBy(step)
}
}
}
parent.performTouchInput {
inRealTime("up()") {
up()
}
}
}
#Test
fun works_simple() {
val anchor = test.onNodeWithText("simple")
val textNode = anchor.onParent()
textNode.printToLog("simple")
selectVertical(anchor, textNode)
}
#Test
fun crash() {
val anchor = test.onNodeWithText("crash")
val textNode = anchor.onParent()
textNode.printToLog("crash")
selectVertical(anchor, textNode)
}
#Test
fun works_space() {
val anchor = test.onNodeWithText("space")
val textNode = anchor.onParent()
textNode.printToLog("space")
selectVertical(anchor, textNode)
}
}
I am working with Firebase so I have a lot of return types of type ApiFuture<A>. I'd like to turn them into a Task[A] to work with ZIO effects.
We can create a method to convert all of them using Typeclasses:
trait EffectUtils[F[_]] {
def toEffect[A](a: F[A]): Task[A]
}
object EffectUtils {
implicit val apiFuture: EffectUtils[ApiFuture] = new EffectUtils[ApiFuture] {
override def toEffect[A](a: ApiFuture[A]): Task[A] = Task.effectAsync[A]( cb =>
ApiFutures.addCallback(a, new ApiFutureCallback[A] {
override def onFailure(t: Throwable): Unit = cb(Task.fail(t))
override def onSuccess(result: A): Unit = cb(Task.succeed(result))
})
)
}
implicit class ApiFutureOps[A](f: ApiFuture[A]) {
def toEffect(implicit instance: EffectUtils[ApiFuture]) = instance.toEffect(f)
}
}
Now, when we make an API request and want to convert the result to a ZIO type, it's easy:
import EffectUtils._
object App {
// calling a Firebase function
val record: Task[UserRecord] = firebase.getInstance().auth().getUserByEmailAsync(email).toEffect
I am trying to get a class to have a property bound to another class's list property, where the 1st property is derived from a summarizing calculation over the objects in the list. The code below is a simplified version of my production code. (The production code is doing a summary over DateTime objects -- the essential part of the code below is the binding between a list and an object property (here, it is a String for simplicity).)
I have tried various things. One approach was using addListener on the list in the Summary class below but I was running into weird bugs with the listener callback making updates on the Summary object. After doing a bunch of reading I think that a binding between the summary string and the list is more appropriate but I don't know exactly how to hook up the binding to the property?
package com.example.demo.view
import javafx.beans.Observable
import javafx.beans.binding.StringBinding
import javafx.beans.property.SimpleIntegerProperty
import javafx.beans.property.SimpleListProperty
import javafx.beans.property.SimpleStringProperty
import javafx.collections.FXCollections
import tornadofx.View
import tornadofx.button
import tornadofx.label
import tornadofx.vbox
class Thing(x: Int) {
val xProperty = SimpleIntegerProperty(x)
val yProperty = SimpleStringProperty("xyz")
}
class Collection {
private var things = FXCollections.observableList(mutableListOf<Thing>()) {
arrayOf<Observable>(it.xProperty)
}
val thingsProperty = SimpleListProperty<Thing>(things)
fun addThing(thing: Thing) {
things.add(thing)
}
}
class Summary(var collection: Collection) {
val summaryBinding = object : StringBinding() {
// The real code is more practical but
// this is just a minimal example.
override fun computeValue(): String {
val sum = collection.thingsProperty.value
.map { it.xProperty.value }
.fold(0, { total, next -> total + next })
return "There are $sum things."
}
}
// How to make this property update when collection changes?
val summaryProperty = SimpleStringProperty("There are ? things.")
}
class MainView : View() {
val summary = Summary(Collection())
override val root = vbox {
label(summary.summaryProperty)
button("Add Thing") {
summary.collection.addThing(Thing(5))
}
}
}
Keep in mind that I made this answer based on your minimal example:
class Thing(x: Int) {
val xProperty = SimpleIntegerProperty(x)
var x by xProperty
val yProperty = SimpleStringProperty("xyz")
var y by yProperty
}
class MainView : View() {
val things = FXCollections.observableList(mutableListOf<Thing>()) {
arrayOf<Observable>(it.xProperty)
}
val thingsProperty = SimpleListProperty<Thing>(things)
val totalBinding = integerBinding(listProperty) {
value.map { it.x }.fold(0, { total, next -> total + next })
}
val phraseBinding = stringBinding(totalBinding) { "There are $value things." }
override val root = vbox {
label(phraseBinding)
button("Add Thing") {
action {
list.add(Thing(5))
}
}
}
}
I removed your other classes because I didn't see a reason for them based on the example. If the collection class has more functionality than holding a list property in your real project, then add just add it back in. If not, then there's no reason to give a list its own class. The summary class is really just two bindings (or one if you have no need to separate the total from the phrase). I don't see the need to give them their own class either unless you plan on using them in multiple views.
I think your biggest problem is that you didn't wrap your button's action in action {}. So your code just added a Thing(5) on init and had no action set.
P.S. The var x by xProperty stuff will only work if you import tornadofx.* for that file.
I know there is the Instrumenter class, however this method outputs the data after the run finish. I would like to get (near) real-time data, like in the Symbolic Regression in the Demos.
Looking at its code, it seems I need to use the step method and try to imitate the runSingleSeed in Executor. Is there a better way? Some other class like Instrumenter but asynchronous. I cannot really find something similar online.
Just build a wrapper around the cycle (similar to the next one) and make it also a subject in an observer pattern.
import java.util.Properties;
import java.util.Arrays;
import java.text.DecimalFormat;
import org.moeaframework.core.Algorithm;
import org.moeaframework.core.Solution;
import org.moeaframework.core.Problem;
import org.moeaframework.core.Population;
import org.moeaframework.core.NondominatedPopulation;
import org.moeaframework.core.variable.EncodingUtils;
import org.moeaframework.core.spi.AlgorithmFactory;
import org.moeaframework.problem.misc.Kursawe;
public class Main{
public static void main(String[] args){
String algorithmName = "NSGAII";
Properties properties = new Properties();
properties.setProperty("populationSize", "100"); // to change properties
Problem problem = new Kursawe();
Algorithm algorithm = AlgorithmFactory.getInstance()
.getAlgorithm(algorithmName, properties, problem);
int maxGenerations = 100;
int generation = 0;
while( generation < maxGenerations ){
if( generation % 10 == 1 ){
System.out.println("Generation " + generation);
NondominatedPopulation paretoFront = algorithm.getResult();
// metrics
System.out.print("One of the pareto front: ");
System.out.println(toString(paretoFront.get(0)));
}
algorithm.step();
generation++;
}
algorithm.terminate();
System.out.println("Parento Front:");
for(Solution solution: algorithm.getResult()){
System.out.println(toString(solution));
}
export(algorithm.getResult());
}
private static String toString(Solution solution){
StringBuilder out = new StringBuilder();
double[] variables = EncodingUtils.getReal(solution);
double[] objectives = solution.getObjectives();
out.append("f");
out.append(doubleArrayToString(variables));
out.append(" = ");
out.append(doubleArrayToString(objectives));
return out.toString();
}
private static String doubleArrayToString(double[] array){
DecimalFormat format = new DecimalFormat("+#,##0.00;-#");
StringBuilder out = new StringBuilder();
out.append("[");
for(int i = 0; i < array.length-1; i++){
out.append(format.format(array[i]));
out.append(", ");
}
out.append(format.format(array[array.length-1]));
out.append("]");
return out.toString();
}
private static void export(Population population){
System.out.println();
for(Solution solution: population){
double[] objectives = solution.getObjectives();
System.out.println(String.format("%.3f,%.3f", objectives[0], objectives[1]));
}
}
}
Another option for the one indicated by Black Arrow, if you are using multithread, is to extentend AlgorithmFactory. For example:
public class MyAlgorithmFactory extends AlgorithmFactory {
private static Algorithm algorithm;
public Algorithm getGeneratedAlgorithm() {
return this.algorithm;
}
#Override
public Algorithm getAlgorithm(String name, Properties properties, Problem problem){
this.algorithm = super.getAlgorithm(name, properties, problem);
return algorithm;
}
}
Then you use this Factory on your Executor, for example:
MyAlgorithmFactory af = new MyAlgorithmFactory();
Executor executor = new Executor()
.usingAlgorithmFactory(af)
.withAlgorithm("NSGAII") //
.withProblem(yourProblemHere) //
.withMaxEvaluations(10000);
After this you can start the Executor on a separated thread, and call af.getGeneratedAlgorithm() to get the instance of Algorithm initialized by the Executor. From this Algorithm you can get, while the Executor is still running, the actual NondominatedPopulation to calc statistics.
Whats the best way to iterate over a Java 8 Stream such that I can perform one function for every element (forEach) while another for every 10 element. Every element using foreach displayed below. What function can I use .to intercept the eveyr nth element and perform the 2nd function call?
Sample code below : -
Stream<String> strings = Files.lines(path); //some stream
stream.forEach(s -> System::println)// every element but how can i perform
Since Guava version 22, you can use Streams.forEachPair to accomplish what you want:
Stream<String> strings = Stream.of("a", "b", "c", "d", "e", "f");
Stream<Long> indexes = Stream.iterate(0L, i -> i + 1L);
Streams.forEachPair(strings, indexes, (s, i) -> {
if (i % 3 == 0) {
System.out.println("Every 3rd element: " + s);
} else {
System.out.println(s);
}
});
This creates an infinite stream of successive Long elements, starting from 0L, and internally zips this stream with the strings stream. Streams.forEachPair accepts a BiConsumer that receives each pair of elements, one from each stream, and performs the action based on whether the index is the 3rd element or not.
You can abstract this more with the following helper method:
static <T> void forEachNthOrElse(
Stream<T> stream,
int n,
Consumer<T> onNthElement,
Consumer<T> onAnyOther) {
Streams.forEachPair(
stream,
Stream.iterate(0L, i -> i + 1),
(t, i) -> {
Consumer<T> action = i % n == 0 ? onNthElement : onAnyOther;
action.accept(t);
});
}
And, for the same example, you can use it as follows:
forEachNthOrElse(
strings,
3,
s -> System.out.println("Every 3rd element: " + s),
System.out::println);
Note: I'm not sure if you need to execute the System.out::println action always, or only when the element is not the nth element. I implemented the BiConsumer to either execute one action or the other. If this is not the case (i.e. if you want to execute one action for the nth element and always execute the other action, even for the nth element), you should change the code accordingly.
Using Vavr(Javaslang) it can be fairly easy by using the provided zipWithIndex method:
stream
.zipWithIndex()
.forEach(t2 -> {
// something that runs for each element
if (t2._2 % 10 == 0) {
// something that runs every 10 elements
}
});
Since stream don't support chunk/split feature, but I have already answer in other question, so I paste it here. I wish it can helped you, for example:
Stream<String> strings = Files.lines(path); //some stream
// v--- skip the last chunk if the chunk size < 10?
split(strings, 10 , true).forEach((List<String> chunk)->{
// each chunk size is 10 ---^
// v--- Every element using foreach displayed
chunk.forEach(System.out::println);
// v--- another for every 10 element.
System.out.println(chunk);
});
import java.util.ArrayList;
import java.util.List;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.stream.Stream;
import static java.util.stream.StreamSupport.stream;
<T> Stream<List<T>> split(Stream<T> source,
int limit, boolean skipRemainingElements) {
//variables just for printing purpose
Spliterator<T> it = source.spliterator();
long size = it.estimateSize();
int c = it.characteristics();// characteristics
return stream(new AbstractSpliterator<List<T>>(size, c) {
private int thresholds = skipRemainingElements ? limit : 1;
#Override
#SuppressWarnings("StatementWithEmptyBody")
public boolean tryAdvance(Consumer<? super List<T>> action) {
List<T> each = new ArrayList<>(limit);
while (each.size() < limit && it.tryAdvance(each::add)) ;
if (each.size() < thresholds) return false;
action.accept(each);
return true;
}
}, false).onClose(source::close);
}
You could also try writing a stateful method yourself without the use of any third party library, it could look something like this:
public <T> void foreachAndEveryNthDoSpecial( Stream<T> stream, Consumer<T> action, int n, Consumer<T> specialAction){
AtomicInteger count = new AtomicInteger(0);
stream.forEach(t -> {
if(count.incrementAndGet() % n == 0){
specialAction.accept(t);
}
action.accept(t);
});
}
Which then can be called like this:
foreachAndEveryNthDoSpecial(myStream, t -> yourAction, 10, t -> specialAction);