We would like to understand a couple of legacy job-dsl scripts but don't know what "slash operator" means in this context (as it cant be division):
def command = (shells.first() / command)
We have tried to look it up in several Groovy books but only found the trivial solution that it means 'division'.
It's an XML Node operation, to return a sub-node of a XML node, or create it if it doesn't exist. Probably the command node under the first of your shells nodes here.
Groovy allows operator overloading, so it is the same "division" operator, just redefined somewhat. This is common (but also controversial) in other languages allowing operator overloading, but does allow for richer DSLs.
Having had a quick look at (an old copy of) the JobDSL source, it seems that they're doing it using a class NodeEnhancement, notably this JavaDoc:
/**
Add div and leftShift operators to Node.
div - Will return the first child that matches name, and if it doesn't exists, it creates
...
**/
Related
I'm currently trying to learn Nim (it's going slowly - can't devote much time to it). On the other hand, in the interests of getting some working code, I'd like to prototype out sections of a Nim app I'm working on in ruby.
Since mruby allows embedding a ruby subset in a C app, and since nim allows compiling arbitrary C code into functions, it feels like this should be relatively straightforward. Has anybody done this?
I'm particularly looking for ways of using Nim's funky macro features to break out into inline ruby code. I'm going to try myself, but I figure someone is bound to have tried it and /or come up with more elegant solutions than I can in my current state of learning :)
https://github.com/micklat/NimBorg
This is a project with a somewhat similar goal. It targets python and lua at the moment, but using the same techniques to interface with Ruby shouldn't be too hard.
There are several features in Nim that help in interfacing with a foreign language in a fluent way:
1) Calling Ruby from Nim using Nim's dot operators
These are a bit like method_missing in Ruby.
You can define a type like RubyValue in Nim, which will have dot operators that will translate any expression like foo.bar or foo.bar(baz) to the appropriate Ruby method call. The arguments can be passed to a generic function like toRubyValue that can be overloaded for various Nim and C types to automatically convert them to the right Ruby type.
2) Calling Nim from Ruby
In most scripting languages, there is a way to register a foreign type, often described in a particular data structure that has to be populated once per exported type. You can use a bit of generic programming and Nim's .global. vars to automatically create and cache the required data structure for each type that was passed to Ruby through the dot operators. There will be a generic proc like getRubyTypeDesc(T: typedesc) that may rely on typeinfo, typetraits or some overloaded procs supplied by user, defining what has to be exported for the type.
Now, if you really want to rely on mruby (because you have experience with it for example), you can look into using the .emit. pragma to directly output pieces of mruby code. You can then ask the Nim compiler to generate only source code, which you will compile in a second step or you can just change the compiler executable, which Nim will call when compiling the project (this is explained in the same section linked above).
Here's what I've discovered so far.
Fetching the return value from an mruby execution is not as easy as I thought. That said, after much trial and error, this is the simplest way I've found to get some mruby code to execute:
const mrb_cc_flags = "-v -I/mruby_1.2.0_path/include/ -L/mruby_1.2.0_path/build/host/lib/"
const mrb_linker_flags = "-v"
const mrb_obj = "/mruby_1.2.0_path/build/host/lib/libmruby.a"
{. passC: mrb_cc_flags, passL: mrb_linker_flags, link: mrb_obj .}
{.emit: """
#include <mruby.h>
#include <mruby/string.h>
""".}
proc ruby_raw(str:cstring):cstring =
{.emit: """
mrb_state *mrb = mrb_open();
if (!mrb) { printf("ERROR: couldn't init mruby\n"); exit(0); }
mrb_load_string(mrb, `str`);
`result` = mrb_str_to_cstr(mrb, mrb_funcall(mrb, mrb_top_self(mrb), "test_func", 0));
mrb_close(mrb);
""".}
proc ruby*(str:string):string =
echo ruby_raw("def test_func\n" & str & "\nend")
"done"
let resp = ruby """
puts 'this was a puts from within ruby'
"this is the response"
"""
echo(resp)
I'm pretty sure that you should be able to omit some of the compiler flags at the start of the file in a well configured environment, e.g. by setting LD_LIBRARY_PATH correctly (not least because that would make the code more portable)
Some of the issues I've encountered so far:
I'm forced to use mrb_funcall because, for some reason, clang seems to think that the mrb_load_string function returns an int, despite all the c code I can find and the documentation and several people online saying otherwise:
error: initializing 'mrb_value' (aka 'struct mrb_value') with an expression of incompatible type 'int'
mrb_value mrb_out = mrb_load_string(mrb, str);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~
The mruby/string.h header is needed for mrb_str_to_cstr, otherwise you get a segfault. RSTRING_PTR seems to work fine also (which at least gives a sensible error without string.h), but if you write it as a one-liner as above, it will execute the function twice.
I'm going to keep going, write some slightly more idiomatic nim, but this has done what I needed for now.
I see that in the cobertura-maven-plugin, I can configure my instrumentation with both excludes and ignores. What is the difference between these two?
Really sorry, but parroting the horrible documentation is not helpful. You quoted:
You can tell Cobertura to ignore certain classes by passing in "ignore" regular expressions. The ignore pattern can be any valid perl 5 regular expression. This will ignore any calls to any method that matches the ignore regular expression. It will NOT skip over these classes during instrumention. To exclude classes from being instrumented, either exclude them from your fileset or use the alternative method below and specify an excludeClasses pattern.
This inconsistent paragraph starts by stating "...to ignore certain classes by passing in 'ignore' regular expressions.", then a second sentence later, "This will ignore any calls to any method that matches the ignore regular expression."
Well, so which is it? Does "ignore" ignore classes or methods? The command-line reference seems to imply ignore is ignoring a line of code based on RegEx matching (I wish that was true):
None of these interpretations works for <ignore> in the maven plugin.
Experimentally I have found that <exclude> is the way to exclude at the class-level. I have not found a way to exclude at a granularity less then class. However, what they also don't tell you is that <exclude> expects a relative filesystem path, not a Java package.class expression, which means <exclude> expects e.g. one/two/three/Myclass.class, rather then "one.two.three.Myclass".
Ignore and exclude really function nothing alike. Exclude will remove a file from Cobertura's scan. Ignore will remove all usages of a class from contributing to line coverage.
Consider the following code snippet:
public class Foo {
public void someMethod() {
Bar bar = new Bar();
}
}
If you configure <exclude>Foo.class</exclude>, then the entirety of the Foo class will not show up on your reporting.
Semi-confusingly, if you configure <ignore>Foo.class</ignore>, then Foo will still show up on your reporting, but uses of Foo in other classes will be ignored.
If you configure <ignore>Bar.class</ignore>, then the scan of Foo will ignore the line in which Bar is initialized.
To really make that stick, let's talk about why you would use ignore. Let's say that there is an object (such as a Logger) that you do not want to show up in the code coverage scan of any classes. Ignore allows you to do this.
The maven plugin does not contain any documentation for this configuration options (but they are included in the docs). The ant cobertura doc contains the following documentation:
You can tell Cobertura to ignore certain classes by passing in "ignore" regular expressions. The ignore pattern can be any valid perl 5 regular expression. This will ignore any calls to any method that matches the ignore regular expression. It will NOT skip over these classes during instrumention. To exclude classes from being instrumented, either exclude them from your fileset or use the alternative method below and specify an excludeClasses pattern.
See also: https://github.com/cobertura/cobertura/wiki/Ant-Task-Reference#cobertura-instrument-task
In Swift, sometimes, keywords are plain keywords, and some others start with an #.
For instance, weak, unowned, inout, class are plain. But #final, #lazy start with #.
Sometimes, we even have both! prefix and #prefix, infix and #infix for instance.
It is not entirely an Objective-C inheritance since we have #class and not class in Objective-C. I could understand why we have class and not #class in Swift, but since we have #final or #lazy , I would have thought that it should be #weak and not weak.
Why this choice? Is there a kind of intuitive way that should tell: "hey, it is logical that this keyword starts with #?
Even if I think with a preprocessor perspective in mind, it is not obvious that # would call a kind of specific preprocessor before compilation (e.g. #final is not really a kind of preprocessor directive).
#-prefixed items in Swift are not keywords, these are attributes.
Apple's book on Swift says that
Attributes provide more information about a declaration or type. There are two kinds of attributes in Swift, those that apply to declarations and those that apply to types.
Some attributes (such as #objc(isEnabled)) accept parameters.
The main difference between attributes and keywords is that keywords tell the compiler what you are defining (a class, a method, a property, a variable, and so on), while attributes tell the compiler in what contexts you intend to use that definition. For example, you would use a func keyword to tell the compiler that you are defining a function, and decorate that function with an #infix attribute to tell the compiler that you plan to use that function as an infix operator.
To implement a domain specific language, within lua,
I want to add barewords to the language.
So that
print("foo") could be written as print(foo)
The way I have done this is by changing the metatable of the enviroment table _G.
mt = {__index = function(tbl,key) return key end}
setmetatable(_G, mt)
And that works, because retrieving the value of variable foo is done by _G.foo which is equivalent to _G["foo"]
Is this a good approach?
Are there hidden downsides?
Is there a better way?
Can I do it so that barewords only work inside a certain file?
(Perhaps by executing that file, from another luascript, using loadstring)
As soon as someone declares a local with the same name of your "keywords" it will shadow your "keyword/global var" and your mechanism will fail:
print(foo) -- does what you think
local foo = 2
print(foo) -- argh!
and note that you cannot prevent the definition of local variables in a script.
Edit: (answering to a comment).
Are you using a customized Lua engine? You cannot prevent entering local scope, because you are always in local scope. It is exactly the other way around: technically there is no global scope in Lua (with the same meaning as in C, for example). There is a global namespace (implemented as a table), instead. The mechanisms for accessing globals differs between Lua 5.1 (function environments) and Lua 5.2 (implicit _ENV prefixing), but the concept is almost the same.
In particular, when a Lua script is loaded, whether by the interpreter, or by load, loadstring, dofile, etc., it is interpreted as the body of an anonymous function (a closure), usually referred to as the "main chunk". Thus there is always a local scope. In standard Lua you cannot prevent the definition of a local variable when the parser encounters a local statement in the script being loaded.
If you run the following Groovy code, the assertion passes
def foo(a, b) {
a + b
}
assert 'aaabbb' == foo(['aaa', 'bbb'])
This suggests that if a method is called with a List parameter that contains X elements, then the List will be spread and a method with X arguments will be invoked.
Of course, this will only happen if there isn't a method defined with a single parameter of type List (or ancestor thereof).
I only discovered this quite recently when reading another SO Groovy answer. I've never seen it mentioned in the Groovy docs, release notes, or books. Is it a hidden feature, a bug, or just something I've missed?
Going to be removed in Groovy 2 apparently:
http://groovy.329449.n5.nabble.com/removing-features-in-Groovy-2-td4422494.html
JT's first on the to-remove list and it seems everyone (with clout) on Groovy User agrees.