4

I am trying to define a method (called "range") which returns an array. I pass two integers, say m and n, and it returns an array of length (n-m) as it is described in the following listing: Implicitly I suppose n is greater than m. But I would like to impose this condition explicitly. Is there any way to impose this kind of conditions on arguments of methods?

You may suggest I change the method so that I pass m and (n-m) instead of m and n into the method, but it still assumes that n-m is a positive integer. So we need to find a way to impose these types of constrains on method arguments.

public static int[] range(int m, int n) {
    int[] r=new int[n-m];
    for(int i=0; i<n-m; i++)
        r[i]=m+i;

    return r;
}
  • `Math.abs(n-m)` in this case. More generally, you'll probably want to throw an `IllegalArgumentException`. – CollinD Aug 13 '17 at 18:29
  • 2
    `Preconditions.checkArgument(n > m);`? – Oliver Charlesworth Aug 13 '17 at 18:30
  • If you just want to create the array of size equal to the difference, why don't you take the absolute value of (n-m) instead? – Debanik Dawn Aug 13 '17 at 18:30
  • I'd like to get a warning if I pass an invalid set of arguments into method, like when I am supposed to pass an integer into a method but I instead pass a double. –  Aug 13 '17 at 18:32
  • If you are asking "how do I do this at compile time?", then the answer is "you can't" - you can't enforce constraints on data only known at runtime at compile time. – Oliver Charlesworth Aug 13 '17 at 18:34
  • You could throw an Error or Exception : https://www.tutorialspoint.com/java/java_exceptions.htm Or create your own handling system that outputs some usage text `if(n < m)` – K.F Aug 13 '17 at 18:34
  • @ Oliver Charlesworth: Could you please elaborate a little more about class Preconditions? What else is possible to do using this class? It sounds interesting. –  Aug 13 '17 at 18:35
  • 1
    @VahidShirbisheh - It's nothing magic, it's just a [library](https://github.com/google/guava/wiki/PreconditionsExplained) for wrapping up a common pattern - throwing an exception if certain conditions aren't met. – Oliver Charlesworth Aug 13 '17 at 18:36
  • @Oliver Charlesworth: I learned a lot from you comments. Thank you! –  Aug 13 '17 at 18:44
  • I appreciate the quick accept ;-) – GhostCat Aug 13 '17 at 18:54
  • And I thank everybody for their quick and very useful comments. –  Aug 13 '17 at 18:56

2 Answers2

3

You are trying to statically (at compile-time) ensure a post-condition that depends on information that is only available at run-time. This concept is called dependent types. In general, dependent type checking is undecidable. Thus, if you have a language that supports dependent type checking, it is possible to write a program where the type checker cannot tell whether it is type correct. An example for such a language is Idris, which is similar to Haskell. Idris is a language that should only be used for research to get a feeling about how dependent types can actually be used in programming (dependent types are a well known concept from automatic theorem provers).

As far as I am aware, there is no such thing like dependent type checking for Java, thus you can only check pre- and post-conditions dynamically (at run-time), e.g. by throwing an exception if an unexpected case occurred.

Stefan Dollase
  • 4,530
  • 3
  • 27
  • 51
  • 1
    I listened to a podcast about type driven development last week; and was inclined to mention Idris. Good that I didnt do that and leave some space for your answer ;-) ... have my vote for that ;-) – GhostCat Aug 13 '17 at 18:51
  • 1
    Very useful information. I see the problem from a higher level now. Thanks for your answer. –  Aug 13 '17 at 18:53
1

There is no way to express this using the type system (at least not the java type system).

You can do things like:

  • having code that checks such conditions - to throw an IllegalArgumentException
  • use asserts in a similar way (but that requires the JVM to be started with certain parameters)

Meaning: you can have runtime checks; but for "compile" resp. "programming" time - you can only give informal advice (such as detailed javadoc about the contract of the method).

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • 1
    Using javadoc and throwing an IllegalArgumentException sounds good enough. Thanks for your advice. –  Aug 13 '17 at 18:51
  • 1
    @VahidShirbisheh For the record: when going for unchecked exceptions to be thrown - still document them via javadoc! – GhostCat Aug 13 '17 at 18:53