Some optimizations/algorithms make code considerably less readable, so it's useful to keep the ability to disable the complex-and-unwieldily functionality within a file/module so any errors introduced when modifying this code can be quickly tested against the simple code.
Currently using const USE_SOME_FEATURE: bool = true; seems a reasonable way, but makes the code read a little strangely, since USE_SOME_FEATURE is being used like an ifdef in C.
For instance, clippy wants you to write:
if foo {
{ ..other code.. }
} else {
// final case
if USE_SOME_FEATURE {
{ ..fancy_code.. }
} else {
{ ..simple_code.. }
}
}
As:
if foo {
{ ..other code.. }
} else if USE_SOME_FEATURE {
// final case
{ ..fancy_code.. }
} else {
// final case
{ ..simple_code.. }
}
Which IMHO hurts readability, and can be ignored - but is caused by using a boolean where a feature might make more sense.
Is there a way to expose a feature within a file without having it listed in the crate?(since this is only for internal debugging and testing changes to code).
You can use a build script to create new cfg conditions. Use println!("cargo:rustc-cfg=whatever") in the build script, and then you can use #[cfg(whatever)] on your functions and statements.
Related
How to reuse code block which describe similiar ant build logic in groovy?
If we have build logic which was implemented by Groovy AntBuilder, just like code below:
ant.someTask(attr1:value1, attr2:value2) {
configuration1(param1:args1, param2:args2){
similiarStructure(additionalArgs:aaa){
setting1(param5:value5) {
//...blah blah blah
}
//further more settings, may be or may be not the same with similiarStructure below
}
}
configuration2(param3:args3, param4:args4){
similiarStructure(additionalArgs:aaa){
setting1(param5:value5) {
//...blah blah blah
}
//further more settings, may be or may be not the same with similiarStructure below
}
}
}
Are there any ways to reuse Groovy AntBuilder code block, which could brief the statment in configuration2 ?
I've try to predefine closures and inject them in both configuration,
but it fails with property not found exception while initializing closure.
I'll provide two answers so you can select which one is more appropriate for your use case and test it. The solutions depend on at what level you want the shared config.
If you want a more general purpose solution that allows you to share the whole of the similarStructure block, you need to perform some more advanced work. The trick is to ensure that the delegate of the shared configuration closure is set appropriately:
def sharedConfig = {
similarStructure(additionalArgs:aaa) {
setting1(param5:value5) {
//...blah blah blah
}
}
}
ant.someTask(attr1: value1, attr2: value2) {
configuration1(param1:args1, param2:args2){
applySharedConfig(delegate, sharedConfig)
}
configuration2(param3:args3, param4:args4){
applySharedConfig(delegate, sharedConfig)
}
}
void applySharedConfig(builder, config) {
def c = config.clone()
c.resolveStrategy = Closure.DELEGATE_FIRST
c.delegate = builder
c.call()
}
Although the applySharedConfig() method seems ugly, it can be used to share multiple configurations across different tasks.
One thing to bear in mind with this solution is that the resolveStrategy of the closure can be very important. I think both DELEGATE_FIRST and OWNER_FIRST (the default) will work fine here. If you run into what appear to be name resolution problems (missing methods or properties) you should try switching the resolution strategy.
I'll provide two answers so you can select which one is more appropriate for your use case and test it. The solutions depend on at what level you want the shared config.
If you are happy to simply share the closure that goes with similarStructure, then the solution is straightforward:
def sharedConfig = {
setting1(param5:value5) {
//...blah blah blah
}
}
ant.someTask(attr1: value1, attr2: value2) {
configuration1(param1:args1, param2:args2) {
similarStructure(additionalArgs:aaa, sharedConfig)
}
configuration2(param3:args3, param4:args4) {
similarStructure(additionalArgs:aaa, sharedConfig)
}
}
The method that is similarStructure should ensure that the sharedConfig closure is properly configured. I haven't tested this, so I'm not entirely sure. The disadvantage of this approach is that you have to duplicate the similarStructure call with its arguments.
I would like feedback on the best practices for defining plugin tasks that depend on external state (i.e. defined in the build.gradle that referenced the plugin). I'm using extension objects and closures to defer accessing those settings until they're needed and available. I'm also interested in sharing state between tasks, e.g. configuring the outputs of one task to be the inputs of another.
The code uses "project.afterEvaluate" to define the tasks when the required settings have been configured through the extension object. This seems more complex than should be needed. If I move the code out of the "afterEvaluate", it gets compileFlag == null which isn't the external setting. If the code is changed again to use the << or doLast syntax, then it will get the external flag... but then it fails to work with type:Exec and other similarly helpful types.
I feel that I'm fighting Gradle in some ways, which means I don't understand better how to work well with it. The following is a simplified pseudo-code of what I'm using. This works but I'm looking to see if this can be simplified, or indeed what the best practices are. Also, the exception shouldn't be thrown unless the tasks are being executed.
apply plugin: MyPlugin
class MyPluginExtension {
String compileFlag = null
}
class MyPlugin implements Plugin<Project> {
void apply(Project project) {
project.extensions.create("myPluginConfig", MyPluginExtension)
project.afterEvaluate {
// Closure delays getting and checking flag until strictly needed
def compileFlag = {
if (project.myPluginConfig.compileFlag == null) {
throw new InvalidUserDataException(
"Must set compileFlag: myPluginConfig { compileFlag = '-flag' }")
}
return project.myPluginConfig.compileFlag
}
// Inputs for translateTask
def javaInputs = {
project.files(project.fileTree(
dir: project.projectDir, includes: ['**/*.java']))
}
// This is the output of the first task and input to the second
def translatedOutputs = {
project.files(javaInputs().collect { file ->
return file.path.replace('src/', 'build/dir/')
})
}
// Translates all java files into 'translatedOutputs'
project.tasks.create(name: 'translateTask', type:Exec) {
inputs.files javaInputs()
outputs.files translatedOutputs()
executable '/bin/echo'
inputs.files.each { file ->
args file.path
}
}
// Compiles 'translatedOutputs' to binary
project.tasks.create(name: 'compileTask', type:Exec, dependsOn: 'translateTask') {
inputs.files translatedOutputs()
outputs.file project.file(project.buildDir.path + '/compiledBinary')
executable '/bin/echo'
args compileFlag()
translatedOutputs().each { file ->
args file.path
}
}
}
}
}
I'd look at this problem another way. It seems like what you want to put in your extension is really owned by each of your tasks. If you had something that was a "global" plugin configuration option, would it be treated as an input necessarily?
Another way of doing this would have been to use your own SourceSets and wire those into your custom tasks. That's not quite easy enough yet, IMO. We're still pulling together the JVM and native representations of sources.
I'd recommend extracting your Exec tasks as custom tasks with a #TaskAction that does the heavy lifting (even if it just calls project.exec {}). You can then annotate your inputs with #Input, #InputFiles, etc and your outputs with #OutputFiles, #OutputDirectory, etc. Those annotations will help auto-wire your dependencies and inputs/outputs (I think that's where some of the fighting is coming from).
Another thing that you're missing is if the compileFlag effects the final output, you'd want to detect changes to it and force a rebuild (but not a re-translate).
I simplified the body of the plugin class by using the Groovy .with method.
I'm not completely happy with this (I think the translatedFiles could be done differently), but I hope it shows you some of the best practices. I made this a working example (as long as you have a src/something.java) by implementing the translate as a copy/rename and the compile as something that just creates an 'executable' file (contents is just the list of the inputs). I've also left your extension class in place to demonstrate the "global" plug-in config. Also take a look at what happens with compileFlag is not set (I wish the error was a little better).
The translateTask isn't going to be incremental (although, I think you could probably figure out a way to do that). So you'd probably need to delete the output directory each time. I wouldn't mix other output into that directory if you want to keep that simple.
HTH
apply plugin: 'base'
apply plugin: MyPlugin
class MyTranslateTask extends DefaultTask {
#InputFiles FileCollection srcFiles
#OutputDirectory File translatedDir
#TaskAction
public void translate() {
// println "toolhome is ${project.myPluginConfig.toolHome}"
// translate java files by renaming them
project.copy {
includeEmptyDirs = false
from(srcFiles)
into(translatedDir)
rename '(.+).java', '$1.m'
}
}
}
class MyCompileTask extends DefaultTask {
#Input String compileFlag
#InputFiles FileCollection translatedFiles
#OutputDirectory File outputDir
#TaskAction
public void compile() {
// write inputs to the executable file
project.file("$outputDir/executable") << "${project.myPluginConfig.toolHome} $compileFlag ${translatedFiles.collect { it.path }}"
}
}
class MyPluginExtension {
File toolHome = new File("/some/sane/default")
}
class MyPlugin implements Plugin<Project> {
void apply(Project project) {
project.with {
extensions.create("myPluginConfig", MyPluginExtension)
tasks.create(name: 'translateTask', type: MyTranslateTask) {
description = "Translates all java files into translatedDir"
srcFiles = fileTree(dir: projectDir, includes: [ '**/*.java' ])
translatedDir = file("${buildDir}/dir")
}
tasks.create(name: 'compileTask', type: MyCompileTask) {
description = "Compiles translated files into outputDir"
translatedFiles = fileTree(tasks.translateTask.outputs.files.singleFile) {
includes [ '**/*.m' ]
builtBy tasks.translateTask
}
outputDir = file("${buildDir}/compiledBinary")
}
}
}
}
myPluginConfig {
toolHome = file("/some/custom/path")
}
compileTask {
compileFlag = '-flag'
}
I have a List<File> where I would like to ensure that each File element is a directory, and if it is not, throw an exception.
In Java I would do:
List<File> possibleDirs;
...
for (File possibleDir : possibleDirs) {
if (!possibleDir.isDirectory()) throw new Exception();
...
}
but I am wondering if there is a better way to do this in groovy
I am wondering if there is a better way to do this in groovy
What you have there is fine. You could use some Groovy-isms like using a Closure for iterating:
possibleDirs.each { file ->
if(!file.isDirectory()) {
// throw exception...
}
}
Or...
def allAreDirs = possibleDirs.every { file ->
file.isDirectory()
}
if(!allAreDirs) {
// throw exception...
}
I don't think either of those is really any better than what you have. An argument against the every approach is that it has to visit every file where the previous approach and the approach you described bail out as soon as you know there is a problem.
EDIT:
I suppose you could also do something like:
if(possibleDirs.find { !it.isDirectory() }) {
// throw exception...
}
I thought that I had come across this before, but I can't remember when or what language it was.
Basically if I have the following in C#:
someCondition = true
if(someCondition)
{
// Do Something
if(anotherCond) {
someCondition = false;
continue;
}
// Do Something Else
}
In C# this will break out of the body of the if statement when someCondition changes, meaning that //DO Something Else only gets processed if someCondition doesn't change...
Is there a language that will do the interior if statement checking/continue automatically i.e. be able to write:
someCondition = true
if(someCondition)
{
// Do Something
if(anotherCond){
someCondition = false;
}
// Do Something Else
}
with the same behaviors as the previous? Obviously there are multiple ways to get this behavior in every language conceivable, what I am interested in is if there is a language that by design has this functionality.
Edit: Reduced the examples so hopefully people can see what is happening, when someCondition changes (i.e. the condition that the if statement relied on to begin, we should break out of the remaining if statement. I am not looking for a way to do this in C#, or any particular language, but for a language that does this automatically.
You can create a property in C# that throws an exception on any condition you set, aka truth=true. The exception will break out of the loop to wherever you have your catch.
An example in C#:
public class MyException : Exception { }
public bool truth
{
get { return _truth; }
set
{
_truth = value;
if(value)
throw new MyException();
}
}
bool _truth;
I think you can simulate what you want in C# like so:
void ExecuteWhile( Func<bool> condition,
IEnumerable<Action> executeWhileTrue,
IEnumerable<Action> executeWhileFalse)
{
if (condition())
{
foreach (Action action in executeWhileTrue)
{
action();
if (!condition())
return;
}
}
else
{
foreach (Action action in executeWhileFalse)
{
action();
if (condition())
return;
}
}
}
and then use it as such:
truth = true;
while (true) // loop forever
{
ExecuteWhile( () => truth,
new List<Action> { () => { /* do something that might set truth to false*/},
() => { /* do something else*/}},
new List<Action> { () => { /* do something that might set truth to true*/},
() => { /* do something else*/}});
}
And to answer your question: no, I don't think there is a language with this as a build-in feature.
As far as I understood, the following is wanted:
if (cond) {
A;
B;
C;
}
shall behave as if written thus:
if (cond) {
A;
if (cond) {
B;
if (cond) {
C
}
}
}
IMHO, this would be a silly feature, unlikely to be implemented in any language except maybe in INTERCAL.
Why do I think that?
Well, suppose someone wants to refactor the code and moves B;C to a subroutine.
if (cond) {
A;
BC();
}
subroutine BC() { B;C }
The block - according to our feature - will mean as before:
if (cond) {
A;
if (cond) BC();
}
But what about our subroutine? The language designer has 2 choices here:
Treat the call BC() as atomic, i.e. in the subroutine, the
condition cond is not checked before statement C. This would mean
such a simple refactoring would change the meaning of the program
drastically.
Somehow pass the information that every statement must be guarded
with cond to the subroutine so that the behaviour of our block remains
unchanged. This, of course, leads to the silly situation that the
behaviour of any subroutine would depend upon the context it was
called in. A subroutine with n atomic statements would have n possible ways to behave even if it had no arguments and would not use non local mutable state explicitely, depending on how many of the statements would be actually executed. (Note that nowadays the trend is to minimize the most often harmful effects of shared non-local state. OO languages do it with encapsulation, FP languages by banning mutable state altogether.)
In any case, no matter how the language designer decides, we would have a feature that is the direct contradiction of the principle of the least surprise. It is clear that programs in such a language would be utterly hard to maintain.
If you broke you big bunch if/else statements into succinct little methods which tested each little piece of the puzzle, you could rely on the compilers short circuit boolean evaluation
I'm not sure if that helps as your example is a big vague. You don't say if you're doing any processing or if it's just a bunch of checks. Either way, breaking your code into smaller methods may help you out.
You can use a do..while loop:
do
{
} while (truth == true);
thats if i've understood correctly!
You say while true... but while what is true. I would think your loop will run infinitely regardless of the language used. Assuming true will be a real condition... I would say just set the exit condition in one of the if blocks. You question is a bit hard to understand. Also the continue is unnecessary.
I'm trying to write a Greasemonkey script for a hierarchy of websites such that I have a bunch of code modifications for http://www.foo.com/*, then more specific ones for http://www.foo.com/bar/*, and still others for http://www.foo.com/foobar/*.
Is there anyway for me to write all these in the same script, or do I have to make multiple?
Is there anyway for me to write all
these in the same script, or do I have
to make multiple?
Yes, just use those three #includes, then in your user script do something like (depends on specifics of script):
var currentURL = (document.location+'');
if (currentURL .match(/http:\/\/www\.foo\.com\/foobar\/.*/)) {
// do stuff for page set A
} else if (currentURL .match(/http:\/\/www\.foo\.com\/foo\/.*/)) {
// do stuff for page set B
} else if (currentURL .match(/http:\/\/www\.foo\.com\/.*/)) {
// do stuff for page set C
}
One nifty trick I was shown for dealing with different functions at different sub-locations is to use the global directory of function names as a sort of virtual switchboard...
// do anything that is supposed to apply to the entire website above here.
var place = location.pathname.replace(/\/|\.(php|html)$/gi, "").toLowerCase();
// the regex converts from "foo/" or "foo.php" or "foo.html" to just "foo".
var handler;
if ((handler = global["at_" + place])) {
handler();
}
// end of top-level code. Following is all function definitions:
function at_foo() {
// do foo-based stuff here
}
function at_foobar() {
// do foobar stuff here.
}