Parsing a String to Option[LocalDateTime] - scala

I wrote a TimeFormatter to parse a String to an Option[LocalDateTime].
The API notes that either exception could be thrown.
private def convertToDateTime(date: String): Option[LocalDateTime] =
try {
Some( timeFormatter.parseLocalDateTime(date) )
}
catch { // DateTimeFormatter#parseLocalDateTime API throws these possible exceptions
case e # (_: IllegalArgumentException | _: UnsupportedOperationException) =>
log.error(s"Could not convert $date to LocalDateTime", e); None
}
Joshua Bloch notes:
Item 39: Use exceptions only for exceptional conditions.
I thought of using a regular expression to catch an error. But, I'm not sure if my reg-ex will always match jodatime's way of parsing the String to a LocalDateTime. I can trust that the API will throw those exceptions, but I'd rather not rely upon internals of the method call with a reg-ex.
From a functional point of view, I'd rather not use exceptions.
How can I write this function without exceptions?

There is nothing wrong with your code : you are not using exceptions to model non-exceptional conditions. You are handling conversion errors and turning them into a value to be returned which is perfectly acceptable.
Jodatime is using exceptions to signal invalid input (maybe not so exceptional) or the unavailability of a part of its API (completely exceptional), this is common practice in the Java world.
To actually parse dates without exceptions entirely you would need to find or reimplement a date handling library which is quite a huge endeavour.
A silent alternative to your method:
private def convertToDateTime(date: String): Option[LocalDateTime] =
Try(timeFormatter.parseLocalDateTime(date)).toOption

I have experimented with Joda-Time and found this half solution avoiding runtime exceptions even in case of wrong input:
String input = "2015-02-a29 15:24:33";
DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
DateTimeParser parser = dtf.getParser();
Chronology chronology = ISOChronology.getInstanceUTC();
DateTimeParserBucket bucket =
new DateTimeParserBucket(0L, chronology, Locale.getDefault(), 2000, 2000);
int result = parser.parseInto(bucket, input, 0);
System.out.println(result);
if (result < 0) {
System.out.println("Parsing failed at position: " + ~result);
} else {
System.out.println(new LocalDateTime(bucket.computeMillis(), chronology));
}
The output is for the given input:
-9
Parsing failed at position: 8
This is in agreement with the javadoc. However, the bad news is that this solution is not perfect. If you use the input 2015-02-29 15:24:33 (an invalid date in non-leap-year) then you get an exception because Joda-Time does not recognize in the method parseInto(...) that the parsed day-of-month is out of range and unfortunately sees it too late, namely in the method computeMillis(). The output is here:
19 // should have been negative - probably a bug!!!
Exception in thread "main" org.joda.time.IllegalFieldValueException: Value 29 for dayOfMonth must be in the range [1,28]
at org.joda.time.field.FieldUtils.verifyValueBounds(FieldUtils.java:217)
at org.joda.time.field.PreciseDurationDateTimeField.set(PreciseDurationDateTimeField.java:78)
at org.joda.time.format.DateTimeParserBucket$SavedField.set(DateTimeParserBucket.java:483)
at org.joda.time.format.DateTimeParserBucket.computeMillis(DateTimeParserBucket.java:365)
at org.joda.time.format.DateTimeParserBucket.computeMillis(DateTimeParserBucket.java:318)
at JodaPeriod.main(JodaPeriod.java:31)
Of course, for the valid input 2015-02-28 15:24:33 all is fine, and the output is
19
2015-02-28T15:24:33.000
I agree with Joshua Bloch that catching exceptions should only be used in exceptional situations. In my company architects say: Don't use exceptions for programming logic. Sometimes it is good for performance to avoid exceptions when ever possible in use-cases like processing a lot of possibly wrong data. A good API should therefore support similar solutions.
Note that other date-and-time-libraries have this option, too. For example java.text.SimpleDateFormat using an instance of class ParsePosition (there the API is even much simpler and smoothly works - although not thread-safe).

You could use the Exception api in scala.control to transform exceptions:
Your function would look something like this:
import scala.util.control.Exception._
private def convertToDateTime(date: String): Option[LocalDateTime] =
catching(classOf[Exception]) opt timeFormatter.parseLocalDateTime(date)

Related

Why is generic instantiation syntax disallowed in Hack?

From the docs:
Note: HHVM allows syntax such as $x = Vector<int>{5,10};, but Hack
disallows the syntax in this situation, instead opting to infer
it.
Is there a specific reason for this? Isn't this a violation of the fail-fast rule?
There are some situations in which this would cause error to be deffered, which in turn leads to harder backtracing.
For example:
<?hh // strict
function main() : void {
$myVector = new Vector([]); // no generic syntax
$myVector->addAll(require 'some_external_source.php');
}
The above code causes no errors until it is used in a context where the statically-typed collection is actually in place:
class Foo
{
public ?Vector<int> $v;
}
$f = new Foo();
$f->v = $myVector;
Now there is an error if the vector contains something else then int. But one must trace back the error to the point where the flawed data was actually imported. This would not be necessary if one could instantiate the vector using generic syntax in the first place:
$myVector = new Vector<int>([]);
$myVector->addAll(require 'some_external_source.php'); // fail immediately
I work on the Hack type system and typechecker at Facebook. This question has been asked a few times internally at FB, and it's good to have a nice, externally-visible place to have an answer to it written down.
So first of all, your question is premised on the following code:
<?hh // strict
function main() : void {
$myVector = new Vector([]); // no generic syntax
$myVector->addAll(require 'some_external_source.php');
}
However, that code does not pass the typechecker due to the usage of require outside toplevel, and so any result of actually executing it on HHVM is undefined behavior, rendering this whole discussion moot for that code.
But it's still a legitimate question for other potential pieces of code that do actually typecheck, so let me go ahead and actually answer it. :)
The reason that it's unsupported is because the typechecker is actually able to infer the generic correctly, unlike many other languages, and so we made the judgement call that the syntax would get in the way, and decided to disallow it. It turns out that if you just don't worry about, we'll infer it right, and still give useful type errors. You can certainly come up with contrived code that doesn't "fail fast" in the way you want, but it's, well, contrived. Take for example this fixup of your example:
<?hh // strict
function main(): void {
$myVector = Vector {}; // I intend this to be a Vector<int>
$myVector[] = 0;
$myVector[] = 'oops'; // Oops! Now it's inferred to be a Vector<mixed>
}
You might argue that this is bad, because you intended to have a Vector<int> but actually have a Vector<mixed> with no type error; you would have liked to be able to express this when creating it, so that adding 'oops' into it would cause such an error.. But there is no type error only because you never actually tried to use $myVector! If you tried to pull out any of its values, or return it from the function, you'd get some sort of type compatibility error. For example:
<?hh // strict
function main(): Vector<int> {
$myVector = Vector {}; // I intend this to be a Vector<int>
$myVector[] = 0;
$myVector[] = 'oops'; // Oops! Now it's inferred to be a Vector<mixed>
return $myVector; // Type error!
}
The return statement will cause a type error, saying that the 'oops' is a string, incompatible with the int return type annotation -- exactly what you wanted. So the inference is good, it works, and you don't ever actually need to explicitly annotate the type of locals.
But why shouldn't you be able to if you really want? Because annotating only generics when instantiating new objects isn't really the right feature here. The core of what you're getting at with "but occasionally I really want to annotate Vector<int> {}" is actually "but occasionally I really want to annotate locals". So the right language feature is not to let you write $x = Vector<int> {}; but let you explicitly declare variables and write Vector<int> $x = Vector {}; -- which also allows things like int $x = 42;. Adding explicit variable declarations to the language is a much more general, reasonable addition than just annotating generics at object instantiation. (It's however not a feature being actively worked on, nor can I see it being such in the near to medium term future, so don't get your hopes up now. But leaving the option open is why we made this decision.)
Furthermore, allowing either of these syntaxes would be actively misleading at this point in time. Generics are only enforced by the static typechecker and are erased by the runtime. This means that if you get untyped values from PHP or Hack partial mode code, the runtime cannot possibly check the real type of the generic. Noting that untyped values are "trust the programmer" and so you can do anything with them in the static typechecker too, consider the following code, which includes the hypothetical syntax you propose:
<?hh // partial
function get_foo() /* unannotated */ {
return 'not an int';
}
<?hh // strict
function f(): void {
$v = Vector<int> {};
$v[] = 1; // OK
// $v[] = 'whoops'; // Error since explicitly annotated as Vector<int>
// No error from static typechecker since get_foo is unannotated
// No error from runtime since generics are erased
$v[] = get_foo();
}
Of course, you can't have unannotated values in 100% strict mode code, but we have to think about how it interacts with all potential usages, including untyped code in partial mode or even PHP.

GWT JSONParser.parseStrict

I have been using JSONParser's parse method without many issues.
Recently, I decided to pay attention to a deprecation notice that I had been seeing. It recommended that I use either parseStrict or parseLenient.
So, I decided to try out parseStrict.
I declared a json string...
String jsonstr = "{value : [12,34],[56,78]]}";
...I confirmed that it worked with good old parse...
JSONValue jsv = JSONParser.parse(jsonstr);
...and an alert window tells me value of jsv was this:
{"value" : [12,34],[56,78]]}
Then I used parseStrict on the same string:
JSONValue jsv = JSONParser.parseStrict(jsonstr);
But my GWT app crashed with an exception!
What are the requirements in using parseStrict (vs parse)? Wny did it trip on such a simple little json string?
Uncaught exception escaped
com.google.gwt.event.shared.UmbrellaException: One or more exceptions caught, see full set in UmbrellaException#getCauses
at com.google.gwt.event.shared.HandlerManager.fireEvent(HandlerManager.java:129)
......
at com.google.gwt.json.client.JSONParser.evaluate(JSONParser.java)
at com.google.gwt.json.client.JSONParser.parse(JSONParser.java:218)
at com.google.gwt.json.client.JSONParser.parseStrict(JSONParser.java:87)
In the strictest sense, the JSON you've provided just isn't strictly correct.
JSON key values should be surrounded by double quotes as described in the JSON spec, so your example JSON should be as follows:
String jsonstr = "{\"value\" : [[12,34],[56,78]]}";
Also, it appears that your braces ([]) don't match up (which I have also corrected).
In summary, it could be either the missing matching brace, or the lack of double quotes. To find out, you can wrap the offending code in a try / catch block and do as the stack trace suggests. Namely, call the getCauses method on the exception:
try {
JSONValue jsv = JSONParser.parseStrict(jsonstr);
} catch (UmbrellaException e) {
Set causes = e.getCauses();
//actually find out what the problem was
}
Note: JSONParser.parse just uses eval under the hood so be careful when using it!

How to check for null in a single statement in scala?

In my scala code:
QueueManager.add(getObject)
where getObject is a method that returns an object of type QueueObject.
def getObject : QueuObject = {
val response = //some response
return response
}
Is there a way I can check for the response being null, while adding the QueueObject? I know I can do this:
if (getObject != null)
QueueManager.add(getObject)
But I do not wish to add a level of indentation. Is there an operator that does that inline?
Thanks.
Try to avoid using null in Scala. It's really there only for interoperability with Java. In Scala, use Option for things that might be empty. If you're calling a Java API method that might return null, wrap it in an Option immediately.
def getObject : Option[QueueObject] = {
// Wrap the Java result in an Option (this will become a Some or a None)
Option(someJavaObject.getResponse)
}
Note: You don't need to put it in a val or use an explicit
return statement in Scala; the result will be the value of
the last expression in the block (in fact, since there's only one statement, you don't even need a block).
def getObject : Option[QueueObject] = Option(someJavaObject.getResponse)
Besides what the others have already shown (for example calling foreach on the Option, which might be slightly confusing), you could also call map on it (and ignore the result of the map operation if you don't need it):
getObject map QueueManager.add
This will do nothing if the Option is a None, and call QueueManager.add if it is a Some.
I find using a regular if however clearer and simpler than using any of these "tricks" just to avoid an indentation level. You could also just write it on one line:
if (getObject.isDefined) QueueManager.add(getObject.get)
or, if you want to deal with null instead of using Option:
if (getObject != null) QueueManager.add(getObject)
edit - Ben is right, be careful to not call getObject more than once if it has side-effects; better write it like this:
val result = getObject
if (result.isDefined) QueueManager.add(result.get)
or:
val result = getObject
if (result != null) QueueManager.add(result)
Option(getObject) foreach (QueueManager add)
If it instead returned Option[QueueObject] you could use a construct like getObject.foreach { QueueManager.add }. You can wrap it right inline with Option(getObject).foreach ... because Option[QueueObject](null) is None.
Although I'm sure #Ben Jackson's asnwer with Option(getObject).foreach is the preferred way of doing it, I like to use an AnyRef pimp that allows me to write:
getObject ifNotNull ( QueueManager.add(_) )
I find it reads better.
And, in a more general way, I sometimes write
val returnVal = getObject ifNotNull { obj =>
returnSomethingFrom(obj)
} otherwise {
returnSomethingElse
}
... replacing ifNotNull with ifSome if I'm dealing with an Option. I find it clearer than first wrapping in an option and then pattern-matching it.
(For the implementation, see Implementing ifTrue, ifFalse, ifSome, ifNone, etc. in Scala to avoid if(...) and simple pattern matching and the Otherwise0/Otherwise1 classes.)

Early return from a Scala constructor

I am writing the constructor for my "main" class. The first thing it does is call a method to use commons-cli to parse the command line. If the parseOptions method returns false, an error has occurred, and the constructor should exit.
I tried writing the following code
if (!parseOptions(args)) return
but the compiler complains that I have a "Return statement outside method definition".
Short of calling System.exit(1) or inverting the boolean (and putting all of the rest of my logic inside the if statement, is there any way to return "early" from a constructor?
I suppose I could have the parseOptions method throw an IllegalArgumentException and catch that in my Main object.
Thanks.
Dont try to do a early/premature return, this makes your code harder more complex, since the side effects of the return can be hard to understand. Instead use a exception to signal that something is wrong.
You can use require in the constructor. This doesn't return. But it seems like throwing an exception actually fits his situation better.
As in:
class MyTest(
private var myValue: Int ){
require(myValue > 0) // Connected to constructor
}
defined class MyTest
scala> val x = new MyTest(10)
x: MyTest = MyTest#49ff4282
scala> val y = new MyTest(-10)
java.lang.IllegalArgumentException: requirement failed
at scala.Predef$.require(Predef.scala:133)
is there any way to return "early" from a constructor
No. But in your case it sounds like bad design, anyway.
If the parseOptions method returns false, an error has occurred
In this case the constructor should throw an exception, not return normally.
A constructor should always either complete fully, or abort (throw an exception). Anything else leaves your object "half constructed" and thus impossible to reason about.
If in your case, the object is valid even if parseOptions failed, then you can change the condition and continue:
if (parseOptions(args)) {
// rest of constructor
}

Scala problem with jMock expectations and returning a value from mock

Solved. IntelliJ didn't highlight the fact that my imports were incomplete.
Hi,
I have a simple Scala program that I'm trying to develop using jMock. Setting basic expectations works nicely but for some reason Scala does not understand my attempt to return a value from a mock object. My maven build spews out the following error
TestLocalCollector.scala:45: error: not found: value returnValue
one (nodeCtx).getParameter("FilenameRegex"); will( returnValue(regex))
^
And the respective code snippets are
#Before def setUp() : Unit = { nodeCtx = context.mock(classOf[NodeContext]) }
...
// the value to be returned
val regex = ".*\\.data"
...
// setting the expectations
one (nodeCtx).getParameter("FilenameRegex"); will( returnValue(regex))
To me it sounds that Scala is expecting that the static jMock method returnValue would be a val? What am I missing here?
Are you sure about the ';'?
one (nodeCtx).getParameter("FilenameRegex") will( returnValue(regex))
might work better.
In this example you see a line like:
expect {
one(blogger).todayPosts will returnValue(List(Post("...")))
}
with the following comment:
Specify what the return value should be in the same expression by defining "will" as Scala infix operator.
In the Java equivalent we would have to make a separate method call (which our favorite IDE may insist on putting on the next line!)
one(blogger).todayPosts; will(returnValue(List(Post("..."))))
^
|
-- semicolon only in the *Java* version
The OP explains it himself:
the returnValue static method was not visible, thus the errors.
And the will method just records an action on the latest mock operation, that's why it can be on the next line or after the semicolon :)
import org.jmock.Expectations
import org.jmock.Expectations._
...
context.checking(
new Expectations {
{ oneOf (nodeCtx).getParameter("FilenameRegex") will( returnValue(".*\\.data") ) }
}
)