I wrote a method in Groovy using the range operator in order to execute the same code multiple times:
/**
* Prints the {#code files} {#code copyCount} times using
* {#code printService}.
* <p>
* Exceptions may be thrown.
* #param printService Print service
* #param files List of {#code File} objects
* #param copyCount Number of copies to print
*/
private static void printJob(
PrintService printService,
List<File> files,
int copyCount) {
// No multiple copy support for PS files, must do it manually
for ( i in 1..copyCount ) {
// Print files
}
}
This method did not pass unit testing as it badly fails when copyCount is 0.
I searched the documentation and it seems that Groovy implements ranges like a "list of sequential values". As I understand, a range does not represent a representation of an interval of integers since it also has the notion of order embedded.
In Groovy a..b is not the set of integers x such that a <= x <= b.
In Groovy a..b is the representation of the enumeration u: [0,|b-a|] -> [a..b] defined as: u(0) = a, for all i in [1,|b-a|], u(i) = u(i-1) + sgn(b-a)
Now I can fix my code:
if (copyCount > 0) for ( i in 1..copyCount ) {
// Print files
}
Also in Groovy a..<b is the representation of the enumeration u: [0,|b-a|-1] -> [a..b-1] defined as: u(0) = a, for all i in [1,|b-a|-1], u(i) = u(i-1) + sgn(b-a)
I noticed that the code below is also working for copyCount positive or zero:
for ( i in 0..<copyCount ) {
// Print files
}
Still, if I can choose a solution where damages are minimized in case of inconsistency (say copyCount is -200, I may get 200 prints)...
0.step(copyCount, 1) {
// Print files
}
At least with this solution I get a GroovyRuntimeException: Infinite loop in case of a negative copyCount. It is groovy but not very pretty and I feel like I’m playing with fire.
There is also this solution, but I find it ugly.
for ( i in 0..<[0,n].max() ) {
// Print files
}
Therefore, in this case, I think the best is to avoid using the range operator, because it may be confusing for developers that are used to Perl, Ruby or Mathematics, or French (there is no word for this definition of range in French, we would just say "intervalle" for a range)... I also found it safer in case of inconsistency. Still, it is not so groovy.
for ( i = 1 ; i <= copyCount ; i++ ) {
// Print files
}
Why does the range operator in Groovy is so complicated? As I see it, the fact that the step is "magically" determined and that we can’t force it (like in Ruby) is a big flaw in this implementation. Am I the only one who was ever troubled by this (two prints instead of none, it would have been a bad bug ^^ )? Did I miss something? Is there any practical case where it is required for a range to revert order when the higher bound gets lower than the lower bound? Am I being too picky?
Related
I'm trying to port code from DML 1.2 to DML 1.4. Here is part of code that i ported:
group rx_queue [i < NQUEUES] {
<...>
param desctype = i < 64 #? regs.SRRCTL12[i].DESCTYPE.val #: regs.SRRCTL2[i - 64].DESCTYPE.val; // error occurs here
<...>
}
Error says:
error: non-constant expression: cast(i, int64 ) < 64
How can i specify parameter dependent on index value?
I tried to use if...else instead ternary operator, but it says that conditional parameters are not allowed in DML.
Index parameters in DML are a slightly magical expressions; when used from within parameters, they can evaluate to either a constant or a variable depending on where the parameter is used from. Consider the following example:
group g[i < 5] {
param x = i * 4;
method m() {
log info: "%d", x;
log info: "%d", g[4 - i].x;
log info: "%d", g[2].x;
}
}
i becomes an implicit local variable within the m method, and in params, indices are a bit like implicit macro parameters. When the compiler encounters x in the first log statement, the param will expand to i * 4 right away. In the second log statement, the x param is taken from an object indexed with the expression 4 - i, so param expansion will instead insert (5 - i) * 4. In the third log statement, the x param is taken from a constant indexed object, so it expands to 2 * 4 which collapses into the constant 8.
Most uses of desctype will likely happen from contexts where indices are variable, and the #? expression requires a constant boolean as condition, so this will likely give an error as soon as anyone tries to use it.
I would normally advise you to switch from #? to ? in the definition of the desctype param, but that fails in this particular case: DMLC will report error: array index out of bounds on the i - 64 expression. This error is much more confusing, and happens because DMLC automatically evaluates every parameter once with all zero indices, to smoke out misspelled identifiers; this will include evaluation of SRRCTL2[i-64] which collapses into SRRCTL2[-64] which annoys DMLC.
This is arguably a compiler bug; DMLC should probably be more tolerant in this corner. (Note that even if we would remove the zero-indexed validation step from the compiler, your parameter would still give the same error message if it ever would be explicitly referenced with a constant index, like log info: "%d", rx_queue[0].desctype).
The reason why you didn't get an error in DML 1.2 is that DML 1.2 had a single ternary operator ? that unified 1.4's ? and #?; when evaluated with a constant condition the dead branch would be disregarded without checking for errors. This had some strange effects in other situations, but made your particular use case work.
My concrete advise would be to replace the param with a method; this makes all index variables unconditionally non-constant which avoids the problem:
method desctype() -> (uint64) {
return i < 64 ? regs.SRRCTL12[i].DESCTYPE.val : regs.SRRCTL2[i - 64].DESCTYPE.val;
}
I need to evaluate a dynamic logical expression and I know that in ABAP it is not possible.
I found the class cl_java_script and with this class I could achieve my requeriment. I've try something like this:
result = cl_java_script=>create( )->evaluate( `( 1 + 2 + 3 ) == 6 ;` ).
After the method evaluate execution result = true as espected. But my happiness is over when I look into the class documentation that says This class is obsolete.
My question is, there is another way to achieve this?
Using any turing complete language to parse a "dynamic logical expression" is a terrible idea, as an attacker might be able to run any program inside your expression, i.e. while(true) { } will crash your variant using cl_java_script. Also although I don't know the details of cl_java_script, I assume it launches a separate JS runtime in a separate thread somewhere, this does not seem to be the most efficient choice to calculate such a small dynamic expression.
Instead you could implement your own small parser. This has the advantage that you can limit what it supports to the bare minimum whilst being able to extend it to everything you need in your usecase. Here's a small example using reverse polish notation which is able to correctly evaluate the expression you've shown (using RPN simplifies parsing a lot, though for sure one can also build a full fledged expression parser):
REPORT z_expr_parser.
TYPES:
BEGIN OF multi_value,
integer TYPE REF TO i,
boolean TYPE REF TO bool,
END OF multi_value.
CLASS lcl_rpn_parser DEFINITION.
PUBLIC SECTION.
METHODS:
constructor
IMPORTING
text TYPE string,
parse
RETURNING VALUE(result) TYPE multi_value.
PRIVATE SECTION.
DATA:
tokens TYPE STANDARD TABLE OF string,
stack TYPE STANDARD TABLE OF multi_value.
METHODS pop_int
RETURNING VALUE(result) TYPE i.
METHODS pop_bool
RETURNING VALUE(result) TYPE abap_bool.
ENDCLASS.
CLASS lcl_rpn_parser IMPLEMENTATION.
METHOD constructor.
" a most simple lexer:
SPLIT text AT ' ' INTO TABLE tokens.
ASSERT lines( tokens ) > 0.
ENDMETHOD.
METHOD pop_int.
DATA(peek) = stack[ lines( stack ) ].
ASSERT peek-integer IS BOUND.
result = peek-integer->*.
DELETE stack INDEX lines( stack ).
ENDMETHOD.
METHOD pop_bool.
DATA(peek) = stack[ lines( stack ) ].
ASSERT peek-boolean IS BOUND.
result = peek-boolean->*.
DELETE stack INDEX lines( stack ).
ENDMETHOD.
METHOD parse.
LOOP AT tokens INTO DATA(token).
IF token = '='.
DATA(comparison) = xsdbool( pop_int( ) = pop_int( ) ).
APPEND VALUE #( boolean = NEW #( comparison ) ) TO stack.
ELSEIF token = '+'.
DATA(addition) = pop_int( ) + pop_int( ).
APPEND VALUE #( integer = NEW #( addition ) ) TO stack.
ELSE.
" assumption: token is integer
DATA value TYPE i.
value = token.
APPEND VALUE #( integer = NEW #( value ) ) TO stack.
ENDIF.
ENDLOOP.
ASSERT lines( stack ) = 1.
result = stack[ 1 ].
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
" 1 + 2 + 3 = 6 in RPN:
DATA(program) = |1 2 3 + + 6 =|.
DATA(parser) = NEW lcl_rpn_parser( program ).
DATA(result) = parser->parse( ).
ASSERT result-boolean IS BOUND.
ASSERT result-boolean->* = abap_true.
SAPs BRF is an option, but potentially massive overkill in your scenario.
Here is a blog on calling BRF from abap.
And here is how Rules/Expressions can be defined dynamically.
BUT, if you know enough about the source problem to generate
1 + 2 + 3 = 6
Then it is hard to imagine why a simple custom parser cant be used.
Just how complex should the expressions be ?
Id probably write my own parser before investing in calling BRF.
Since some/many BSPs use server side JAVAscript and not ABAP as the scripting language, i cant see SAP removing the Kernel routine anytime soon.
SYSTEM-CALL JAVA SCRIPT EVALUATE.
SO maybe consider Just calling the cl_java_script anyway until it is an issue.
Then worry about a parser if and when it is really no longer a valid call.
But definitely some movement in the obsolete space here.
SAP is pushing/forcing you to cloud with the SDK, to execute such things.
https://sap.github.io/cloud-sdk/docs/js/overview-cloud-sdk-for-javascript
In the documentation of compareTo function, I read:
Returns zero if this object is equal to the specified other object, a
negative number if it's less than other, or a positive number if it's
greater than other.
What does this less than or greater than mean in the context of strings? Is -for example- Hello World less than a single character a?
val epicString = "Hello World"
println(epicString.compareTo("a")) //-25
Why -25 and not -10 or -1 (for example)?
Other examples:
val epicString = "Hello World"
println(epicString.compareTo("HelloWorld")) //-55
Is Hello World less than HelloWorld? Why?
Why it returns -55 and not -1, -2, -3, etc?
val epicString = "Hello World"
println(epicString.compareTo("Hello World")) //55
Is Hello World greater than Hello World? Why?
Why it returns 55 and not 1, 2, 3, etc?
I believe you're asking about the implementation of compareTo method for java.lang.String. Here is a source code for java 11:
public int compareTo(String anotherString) {
byte v1[] = value;
byte v2[] = anotherString.value;
if (coder() == anotherString.coder()) {
return isLatin1() ? StringLatin1.compareTo(v1, v2)
: StringUTF16.compareTo(v1, v2);
}
return isLatin1() ? StringLatin1.compareToUTF16(v1, v2)
: StringUTF16.compareToLatin1(v1, v2);
}
So we have a delegation to either StringLatin1 or StringUTF16 here, so we should look further:
Fortunately StringLatin1 and StringUTF16 have similar implementation when it comes to compare functionality:
Here is an implementation for StringLatin1 for example:
public static int compareTo(byte[] value, byte[] other) {
int len1 = value.length;
int len2 = other.length;
return compareTo(value, other, len1, len2);
}
public static int compareTo(byte[] value, byte[] other, int len1, int len2) {
int lim = Math.min(len1, len2);
for (int k = 0; k < lim; k++) {
if (value[k] != other[k]) {
return getChar(value, k) - getChar(other, k);
}
}
return len1 - len2;
}
As you see, it iterated over the characters of the shorter string and in case the charaters in the same index of two strings are different it returns the difference between them. If during the iterations it doesn't find any different (one string is prefix of another) it resorts to the comparison between the length of two strings.
In your case, there is a difference in the first iteration already...
So its the same as `"H".compareTo("a") --> -25".
The code of "H" is 72
The code of "a" is 97
So, 72 - 97 = -25
Short answer: The exact value doesn't have any meaning; only its sign does.
As the specification for compareTo() says, it returns a -ve number if the receiver is smaller than the other object, a +ve number if the receiver is larger, or 0 if the two are considered equal (for the purposes of this ordering).
The specification doesn't distinguish between different -ve numbers, nor between different +ve numbers — and so neither should you. Some classes always return -1, 0, and 1, while others return different numbers, but that's just an implementation detail — and implementations vary.
Let's look at a very simple hypothetical example:
class Length(val metres: Int) : Comparable<Length> {
override fun compareTo(other: Length)
= metres - other.metres
}
This class has a single numerical property, so we can use that property to compare them. One common way to do the comparison is simply to subtract the two lengths: that gives a number which is positive if the receiver is larger, negative if it's smaller, and zero of they're the same length — which is just what we need.
In this case, the value of compareTo() would happen to be the signed difference between the two lengths.
However, that method has a subtle bug: the subtraction could overflow, and give the wrong results if the difference is bigger than Int.MAX_VALUE. (Obviously, to hit that you'd need to be working with astronomical distances, both positive and negative — but that's not implausible. Rocket scientists write programs too!)
To fix it, you might change it to something like:
class Length(val metres: Int) : Comparable<Length> {
override fun compareTo(other: Length) = when {
metres > other.metres -> 1
metres < other.metres -> -1
else -> 0
}
}
That fixes the bug; it works for all possible lengths.
But notice that the actual return value has changed in most cases: now it only ever returns -1, 0, or 1, and no longer gives an indication of the actual difference in lengths.
If this was your class, then it would be safe to make this change because it still matches the specification. Anyone who just looked at the sign of the result would see no change (apart from the bug fix). Anyone using the exact value would find that their programs were now broken — but that's their own fault, because they shouldn't have been relying on that, because it was undocumented behaviour.
Exactly the same applies to the String class and its implementation. While it might be interesting to poke around inside it and look at how it's written, the code you write should never rely on that sort of detail. (It could change in a future version. Or someone could apply your code to another object which didn't behave the same way. Or you might want to expand your project to be cross-platform, and discover the hard way that the JavaScript implementation didn't behave exactly the same as the Java one.)
In the long run, life is much simpler if you don't assume anything more than the specification promises!
I'm using Choco Solver and given an array of int vars, I want a constraint that check that at least one var in the array is equal to a static value...
Something similar to IntConstraintFactory#count but with the following doc :
/**
* Let N be the number of variables of the VARIABLES collection assigned to value VALUE;
* Enforce condition N >= LIMIT to hold.
* <p>
*
* #param VALUE an int
* #param VARS a vector of variables
* #param LIMIT a variable
*/
public static Constraint at_least(int VALUE, IntVar[] VARS, IntVar LIMIT) {
return new Constraint("At least", /* help here ? */);
}
Does someone knows if it exists or how I can implement it efficiently ?
If you want to post constraint atLeast(VALUE,VARS, LIMIT) in Choco Solver, you can simply post count(VALUE,VARS,X), with X an IntVar of initial domain [0,VARS.length], and post arithm(X,">=",LIMIT). This will do the job. There is no need of implementing a specific constraint for that.
If you want to check that at least one variable in VARS is equal to VALUE, it is even simpler, simply post count(VALUE, VARS, X) with [1,VARS.length] as the initial domain for X. So the minimal number of occurrence of VALUE will be at least 1. No need to create a second variable and the arithmetic constraint.
Is there a programming language that supports chained notation a < b < c to be used instead of a < b and b < c in conditional statements?
Example:
if ( 2 < x < 5 )
if ( 2 < x && x < 5 )
First statementlooks better to me, it's easier to understand and the compiler could use transitivity property to warn about mistakes (e.g. 5 < x < 2 would give a warning).
Python does that.
Icon does this, and it is not part of any hacky special-case "chaining"; it is part of Icon's goal-directed evaluation model. Any comparison either succeeds or fails. If it succeeds, it produces the right-hand side. So you can write
if 0 <= i <= j < n then ...
and it works exactly the way you would expect. But it works not just for comparisons but for any expression; this means you can write your own functions that "chain" in exactly the same way. I love this aspect of Icon and wish more languages could incorporate goal-directed evaluation.
N.B. In Guido's paper introducing Python at VHLL (middle 1990s) he mentions Icon explicitly as a source of inspiration in the design of Python.
This sounds like a simple request (and clearly it is simple enough that python implemented it) but it is not necessarily that easy to use. It actually opens up the ability for a lot of errors to be caused.
Specifically, any time that you use functions (or properties in the case of C#, Getters for Java)
So
public int GetX()
{
return 4;
}
(2 < GetX() < 5);
(2 < GetX() > 5);
(5 < GetX() < 2);
Seems like it would be really simple. But problems occur if GetX() has side effects.
private int val = 10;
public int GetCountdown()
{
return val--;
}
(2 < GetCountdown() < 5);
(2 < GetCountdown() > 5);
(5 < GetCountdown() < 2);
In this situation, is "GetCountdown()" decremented twice or just once?
Would the "chained-if-statement" ever shortcut?
Consider the last statments, which roughly evaluates (in english) to "Is 5 less than some value which is less than 2) which should be impossible, but depending on the implementation and side effects, it is possible that some function (Random.NextInt()) could pass both of those tests.
So, for that reason, it would be required that each of the items is only evaluated once, the saved into a local variable for the next comparison. But then you get into shortcutting problems.
public int GetOne()
{
return 1;
}
public int GetVar()
{
return -1;
}
(GetOne() < GetVar() < GetDBVal() < GetUserInput())
Generally, you would want to first check constants and variables before doing a database hit. But if we said (as we said earlier) that all the values must be saved into local variables ahead of time, this means that it might be calling a database hit, and asking the user for information even though "GetVar()" is -1, and so the first comparison fails)
As I said earlier, clearly Python allows this syntax, so it is clearly possible. But, regardless of the technical implications which I have laid out (all of which are easy to design around) it means that your code is less clear because the next person who reads it does not know whether or not you have considered all of this. Whereas, if(x > 2 && x < 5) { } seems clear to me, I know what it does, and I know what the coder intends.