Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Is it a good idea for a task to get values from project properties or variables that can be changed. For example,
task mergeProperties {
def propertiesFile = new File(project.ext.file1)
def propertiesFile2 = new File(project.ext.file2)
def outputFile = new File(project.ext.file3)
inputs.files propertiesFile, propertiesFile2
outputs.file outputFile
doLast {
// merge properties
}
}
This method can be used to merge any two files and write to any file by changing property.ext properties. Is this a good idea? How UP_TO_DATE check works in this case?
Simple answer: No
As long as you do not provide an example use case or scenario that needs the behaviour described above, I think it is a bad idea to let property files or command line values decide on execution logic. This is what code (in your build.gradle) should be about.
Also, doLast (and doFirst) closures are for minor preparation and cleanup jobs, the main task actions should be defined by a #TaskAction in the custom task type definition:
class Merge extends DefaultTask {
#TaskAction
def merge() {
// merge properties
}
}
task mergeProperties(type: Merge) {
inputs.files 'myInputFile1', 'myInputFile2'
outputs.file 'myOutputFile'
}
Now, a special scenario (I can't imagine right now) could use project properties to define the input and output files.
Related
I must write a plugin to compile files of a certain type not covered by an existing plugin.
My initial requirements are simply that if the input file is changed or if the output is missing, then the task will not be up-to-date. In other words, I want the core "working with files" paradigm to work for me.
My first attempt was to declare both inputs and outputs to see if the project would work as most would expect.
class TestPlugin implements Plugin<Project> {
void apply (Project project) {
project.task('compile') {
doFirst {
inputs.files.eachWithIndex { inFilename, idx ->
def inFile = project.file(inFilename)
def outFilename = outputs.files[idx]
def outFile = project.file(outFilename)
logger.info "converting ${inFile} to ${outFile}"
outFile.append "something"
}
}
}
}
}
apply plugin: TestPlugin
compile {
inputs.file "test.in"
outputs.file "test.out"
}
And it does. At this point it does all I need except for one thing: I have to define outputs in correlation with inputs. But defining the outputs is complicated enough to warrant factoring that part of the code into the plugin's task.
My next attempt was to try to get the task to define its outputs but it fails because when the "populate outputs" code executes, inputs is empty and so no outputs are added.
class TestPlugin implements Plugin<Project> {
void apply (Project project) {
project.task('compile') {
inputs.files.each { outputs.files.add(it.replaceFirst(~/\.in$/, '.out')) }
doFirst {
inputs.files.eachWithIndex { inFilename, idx ->
def inFile = project.file(inFilename)
def outFilename = outputs.files[idx]
def outFile = project.file(outFilename)
logger.info "converting ${inFile} to ${outFile}"
outFile.append "something"
}
}
}
}
}
apply plugin: TestPlugin
compile { inputs.file "test.in" }
The above fails with a "path may not be null..." error caused by indexing an empty outputs list (because inputs is empty at the time the task's outer block iterates over inputs.
I tried populating outputs in Project.afterEvaluate and Project.beforeEvaluate but neither worked. The beforeEvaluate closure never executed. The afterEvaluate closure executed, well, after the project was evaluated which means it executed after the task was set as either up-to-date or out-of-date and so it's not useful for what I need.
I also tried Project.configure but that didn't work either.
Then I discovered lazy configuration but since it's incubating I think I should avoid it. I'm assuming that the Java and C plugins don't use incubating features and that leaves me wondering how those plugins are accomplishing the equivalent of lazy configuration.
Then I found Gradle plugin for custom language but it doesn't have an answer. It does, however, have a comment leading me to look at a lot of gradle source code. Again, I don't think I should have to reinvent the wheel.
Lastly, if I have to push the decision to compile into doFirst and not bother with declaring outputs (and thereby abandon task up-to-datedness), then so be it. I just need to know and move on.
For more context, I'm migrating a build away from ant. The two udemy.com classes I took helped me a lot but didn't go far enough to lead me in a confident direction to solve the stated problem. I asked a similar question to one of the instructors and its community to no avail.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I am tying to download some data from parse (a string) and I get the error
"Value of type 'TableViewController' has no member 'place' on the line that says :
self.place.append(spotdetail.name!)
I have this as a global var :
var place = [""]
and this is my code in the ViewDidLoad:
let query = PFObject.query()
query!.findObjectsInBackgroundWithBlock ({ (objects, error) in
if let skateparks = objects {
for object in skateparks {
if let spotdetail = object as PFObject! {
self.place.append(spotdetail.name!)
self.tableView.reloadData()
}
}
}
print(place)
})
What can I change to make it work as I don't understand why it doesn't recognize the var place as it is in the same view controller (tableView)
thanks!
Everywhere in closure you should use self keyword for properties:
print(self.place)
As originaluser2 pointed out you are using a global variable so you do not need to user self.place. Also i'm not sure what you are subclassing in PFObject, but your func name is findObjectsInBackgroundWithBlock and you are reloading your table data there. Always keep in mind that you can only interact with the UI on the main thread. This will cause errors, so you can either pass back a callback, or do a GCD call to the main queue and then reload the data there.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I often write code such as the following
bool myFunct (...)
{
if (something)
{
return false;
}
// .... more code ....
}
The alternative is
bool myFunct (...)
{
if (something)
{
return false;
}
else
{
// .... more code ....
}
}
Of course, that else block is unnecessary, because the early return means that reaching the else statement in the first place is the equivalent of being inside it. Then there's the fact that, to make the compiler happy, I often have to change the structure of the 2nd implementation to
bool myFunct (...)
{
bool retval = true;
if (something)
{
retval = false;
}
else
{
// .... more code ....
}
return retval;
}
which is extra code and looks stupid. My question is, what do the governing authorities and priests say about this type of situation?
Not only it is OK, it is even encouraged in Spartan Programming. According to Spartan Programming - shorter and simpler code is better, and you achive it (among other ways) by fast terminations and avoiding else statements when possible
Under minimizing use of control:
(2) Simplifying conditionals with early return.
(4) Simplifying logic of iteration with early exits (via
return, continue and break statements).
P.S. It seems #Jeff Atwood also likes the spartan programming way
Of course. You're basically writing a guard condition that will stop you trying to perform unnecessary logic. It's fine.
Like many things, it's personal preference, but I prefer to see code written like your second example for simple cases, and the third example for more complex cases. That doesn't mean any are wrong, though.
There's nothing technically wrong with having an else clause for an if clause that does not terminate naturally (e.g., has a return or throw statement), it's just useless.
Several style guidelines argue against it (and several IDE and analysis tools may produce warnings to support these guidelines), but ultimately, it's just a preference.
The 2nd example looks fine to me because, if the code in the first statement is updated like below, it'll prevent unexpected behavior :
bool myFunct (...)
{
if (something)
{
// ... stuff
if (something_else) return false;
}
else
{
// .... more code ....
}
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Is this a proper way to overwite the === method:
def ===(b)
self.venue === b.venue
print " new === !!!!"
end
And how do I call it on objects a and b who (as instances of the same class) both have the variable venue?
I tried puts a.===(b) but it doesn't work. (it says private method called for #<class1:0xsdfsd...>
Yes, it's proper way to overwrite === method.
You can call this method with:
a === b
or
a.===(b)
You have this error probably because you defined === method as private. Define it as a public method (above private keyword) and it should work.
The method should return a true or false, in this case you print something and the return value will always be nil. Try to change the order and use the print first.
Although you can call it using === it is much more common to use the operator in a case-statement or in the grep method.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I've got a list of mouseOver functions, which for other pages will be much longer, so I'm looking for a way to generate the mouseOver functions in a loop.
Here's a small list of 5 functions in an example, by putting that in a single loop functions I should be able to understand how to expand it to more.
function mouseOver1()
{
document.pic.src ="img1.jpg"
}
function mouseOver2()
{
document.pic.src ="img2.jpg"
}
function mouseOver3()
{
document.pic.src ="img3.jpg"
}
function mouseOver4()
{
document.pic.src ="img4.jpg"
}
function mouseOver5()
{
document.pic.src ="img5.jpg"
}
Thanks for your help!!
(Moving discussion from comments)
You don't want to create five different methods. You want one method that can handle all of your situations.
function mouseOver(i) {
document.pic.src="img" + i + ".jpg";
}
And where before you would've called it like this:
mouseOver1();
You now call it like this:
mouseOver(1);
Does that make sense?