string name = null;
name.ToLower();
In most languages such code would compile. Which languages would catch this and the like errors at compile time ?
The only one I know uptil now is elm: http://elm-lang.org
Rust prevents a lot of errors at compile-time. Rust doesn't have runtime exceptions (other than panic! which crashes the program), instead it uses return values for error handling.
let name = None; // error: mismatched types
let name: Option<String> = None; // ok
name.to_lowercase(); // error: no method named `to_lowercase` found for type `Option`
// correct:
match name {
None => { /* handle None */ },
Some(value) => { value.to_lowercase(); },
}
// or to ignore None and crash if name == None
name.unwrap().to_lowercase();
One of Rust's core concepts that no other language has (afaik) is lifetimes, which prevent dangling references at compile-time. However this is something that garbage-collected and reference-counted languages don't need.
Go doesn't have exceptions. Like Rust, it uses return values to signal errors. But it's not null-safe:
// strings can't be nil:
var name string = nil // error: cannot use nil as type string in assignment
// string pointers can:
var name *string = nil // ok
string.ToLower(*name) // panic: runtime error: invalid memory address
The following languages do have exception handling but might still be helpful to answer the question.
Swift is also safer than average, but it does include runtime exceptions. However, Swift's exceptions are more explicit than those of C++, Java, C#, etc. (e.g. you have to prefix each call to a throwing function with try, and a function declaration must specify whether that function may throw).
let name = nil // error: type of expression is ambiguous without more context
let name: String? = nil // ok
name.lowercaseString // error: value of optional type 'String?' not unwrapped; did you mean to use '!' or '?'?
name!.lowercaseString // will crash at runtime with: fatal error: unexpectedly found nil while unwrapping an Optional value
name?.lowercaseString // calls method only if name != nil
Kotlin is a safer JVM-language which also compiles to JavaScript. Kotlin also has exceptions.
val name = null
name.toLowerCase() // compile-error
if (name != null)
name.toLowerCase() // ok
name?.toLowerCase() // call only if non-null
Ada is a language designed for safety-critical purposes. According to http://www.adaic.org/advantages/features-benefits/, its "many built-in checks allow the compiler or linker to detect errors that in a C-based language would only be caught during run-time".
Elm, as the OP noted, is an excellent language without runtime exceptions. Another language that seems to be equally committed to safety is Pony.
https://www.ponylang.io/discover/#exception-safe
Here's a list of languages that by default don't allow variables to be null.
This makes them a lot safer, preventing all NullPointerExceptions at compile-time, and clearer because you know where you're allowed to pass null and where not, simply by looking at the code.
Most of these languages also provide many other compile-time safety features.
Related
I get a compiler error like this:
The type definitions for type '<ExceptionType>' in the signature and implementation are not compatible because the signature requires that the type supports the interface System.Collections.IStructuralEquatable but the interface has not been implemented
I narrowed it down to the fact that my exception's record type contains a field of a function type.
In my real code, I can work around this because I don't need this function in the exception, but I'm still curious, why do I get this error only when I have a signature file and how would I have my exception implement IStructuralEquatable?
Here's my signature file, Test.fsi:
module Test
type exception_type
exception TestException of exception_type
val throw_test_exception: unit -> unit
Here's my implementation file, Test.fs:
module Test
type exception_type = { value: unit -> unit }
exception TestException of exception_type
let throw_test_exception (): unit =
let r = { value = (fun () -> ()) }
raise (TestException r)
When there's no signature file, everything compiles just fine.
For your signature to work you need to define the full type of exception_type in your signature:
test.fsi
module Test
type exception_type = { value: unit -> unit }
...
Then the error will go away.
Signature files are typically not created by hand.. You can create them using the --sig option.
I'm not sure why would you want to pass a function in an exception. This does not make sense to me but if you elaborate your case (in another question), maybe I might be able to offer some suggestions.
I have a function which currently doesn't receive a bool parameter, but then calls another function with a hardcoded bool. We need to remove the hardcoded call and allow a bool to be passed.
I first thought I could try some default parameter - my google searches resulted in that Go apparently doesn't support optional (resp. default) parameter.
So I thought I'd try function overloading.
I found this thread on reddit, which says that it works with a special directive since version 1.7.3:
https://www.reddit.com/r/golang/comments/5c57kg/when_did_function_overloading_get_slipped_in/
I am using 1.8, and still I couldn't get it to work.
I am not even sure I may be allowed to use that directive, but I was speculating that changing the function signature right away may be dangerous as I don't know who uses the function...
Anyway - even with //+overloaded it didn't work
Is there any "idiosyncratic" way or pattern to solve this problem in Go?
//some comment
//+overloaded
func (self *RemoteSystem) Apply(rpath, lpath string, dynamic bool) error {
result, err := anotherFunc(rpath, dynamic)
}
//some comment
//+overloaded
func (self *RemoteSystem) Apply(rpath, lpath string ) error {
//in this function anotherFunc was being called, and dynamic is hardcoded to true
//result, err := anotherFunc(rpath, true)
return self.Apply(rpath, lpath, true)
}
When I run my test, I get (forgive me for omitting part of the real path to file):
too many arguments in call to self.Apply
have (string, string, bool)
want (string, string)
../remotesystem.go:178: (*RemoteSystem).Apply redeclared in this block
previous declaration at ../remotesystem.go:185
Overloading isn't available in Go. Instead of writing functions with the same name that do different things, it is preferable to be more expressive with what the function does in the function name. In this instance, what would commonly be done is something like this:
func (self *RemoteSystem) Apply(rpath, lpath string, dynamic bool) error {
result, err := anotherFunc(rpath, dynamic)
}
func (self *RemoteSystem) ApplyDynamic(rpath, lpath string ) error {
//in this function anotherFunc was being called, and dynamic is hardcoded to true
return self.Apply(rpath, lpath, true)
}
Just by the name of the function, you can easily tell what is different and why.
Another example to provide some context (pun intended).
I write a lot of Google App Engine code in Go using go-endpoints. The way to log things is different depending on if you have a context or not. My logging functions ended up like this.
func LogViaContext(c context.Context, m string, v ...interface{}) {
if c != nil {
appenginelog.Debugf(c, m, v...)
}
}
func LogViaRequest(r *http.Request, m string, v ...interface{}) {
if r != nil {
c := appengine.NewContext(r)
LogViaContext(c, m, v...)
}
}
From the Reddit post:
Unicode. I can tell by the pixels.
Go doesn't support function overloading. But it does support using Unicode characters in function names, which allows you to write function names that look like other function names.
The first one is setValue, the second one is setV\u0430lue aka setV\xd0\xb0lue (with CYRILLIC SMALL LETTER A) and the third is setVal\U0001d69ee aka setVal\xf0\x9d\x9a\x9ee (with MATHEMATICAL MONOSPACE SMALL U).
See also:
Does the Go language have function/method overloading? (stackoverflow.com)
Why does Go not support overloading of methods and operators? (golang.org)
Alternative for function overloading in Go? (stackoverflow.com)
I recently found some go code was running in a test framework where there were some uninitialized variables.
This lead to a panic, which had a stack trace containing some c code at the top.
Is there a way, in functions, that we can concisely detect wether the struct which is referenced as the implementing member is nil? i.e.
func ( d *Dog ) canBark Bool {
//if d is nil, cryptic exception is thrown.
//is there a way to defend against this?
}
The error which is thrown is
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x4ec83a]
goroutine 16 [running]:
runtime.panic(0x9b7400, 0xf7ddf3)
It seems that in go, such lower level errors should occur very rarely, maybe never at all...
There might be a Golang way to deal with nil references which don't clutter the code too much with if/else logic. For example, in java, you can wrap a large code segment in a null pointer exception handler.
You can check for nil and then do whatever:
func (d *Dog) canBark bool {
if d == nil {
// do something useful, maybe? Like log
// a stack trace for debugging later
log.Print("Attempt to bark a nil dog!")
return false
}
// do the regular things
}
Sure:
func ( d *Dog ) bool {
if d == nil {
// a nil dog can't bark
return false
}
}
It's entirely possible to use methods on a nil struct. However, a nil interface is another story. You can't defend against that, because there's no type to call a method on.
type Barker interface {
CanBark() bool
}
var dog Barker
//panics
dog.CanBark()
In go, it's a programming error to improperly initialize a data structure, and methods can panic. If a type value is returned to you from a function or a method, there is generally an error value returned as well indicating whether the first value can be used.
What is the difference between:
var arr3 = new Vector.<int>(6);
to
var arr3:Vector.<int> = new Vector.<int>(6);
Thanks!
It's the difference between declaring a variable type and not. While declaring a type is optional in AS3, best practice is to always declare a type.
The effect on your code this has is that if you declare a type, it will only compile and run properly if values of that type are assigned to the variable, and it will always be treated strictly as that type of object and nothing else. This is called "type safety". If you don't declare a type, you can assign anything to that variable and write code as if its any kind of object -- which may sound convenient, but it ends up making the code much more confusing, fragile and error prone.
Also note that not declaring a type is equivalent to declaring it as a "wildcard" type, like this: var arr3:*
Here's an example of untyped vs typed variables in code:
var untyped:*;
var string:String;
var number:Number;
var integers:Vector.<int>;
untyped = 1; // ok
untyped = "hello"; // ok
untyped = new Vector.<int>(); // ok
string = 1; // compile error
string = "hello"; // ok
string = new Vector.<int>(); // compile error
number = 1; // ok
number = "hello"; // compile error
number = new Vector.<int>(); // compile error
integers = 1; // compile error
integers = "hello"; // compile error
integers = new Vector.<int>(); // ok
if (untyped == 1) // ok
if (untyped == "hello") // ok
if (untyped.fixed) // compiles ok, but throws runtime error if "fixed" not defined on non-dynamic object
if (string == 1) // compile error, invalid comparison
if (string == "hello") // ok
if (string.fixed) // compile error, "fixed" not a property of String
if (number == 1) // ok
if (number == "hello") // compile error, invalid comparison
if (number.fixed) // compile error, "fixed" not a property of Number
if (integers == 1) // compile error, invalid comparison
if (integers == "hello") // compile error, invalid comparison
if (integers.fixed) // ok
These compile errors serve to show you mistakes you (or other developers) make before they become hard to hunt down problems in your SWF. For example, consider this untyped code:
var value = "hello";
if (value.x < 10) { }
That code doesn't make much sense, but it will compile. Then you will hit a runtime error when it tries to execute the if statement and can't find x on String "hello". In real life you might have a lot of hunting around to do to figure out what's wrong, especially if those 2 lines are not in close proximity to each other. However, if the programmer had specified a type on the variable, it would make the code more type safe:
var value:Point;
if (value.x < 10) { }
In this case the code would not compile if you tried to assign value = "hello". The compiler would also validate that x is a property of type Point. If it wasn't, you'd get a compile error there, too. It even knows that x can be compared using < because it's a Number. This is all helpful to catch errors early rather than later.
In addition to making the code more clear to programmers, it also makes it more clear to authoring tools -- most authoring tools will give you much better code-completion suggestions for typed objects, since it knows exactly what properties and methods that type of object has.
For these reasons and probably others, you'll rarely find AS3 code examples that don't use strict type declarations, and most programmers (including me) will advise you always use them.
Use second option. In first case you will get warning message:
Warning: Error code: 1008: variable 'arr3' has no type declaration.
The first variable is untyped. If you declare a variable, but do not declare its data type, the default data type ***** will apply, which actually means that the variable is untyped. If you also do not initialize an untyped variable with a value, its default value is undefined.
The second one is typed as Vector.. A variable declared with the Vector. data type can only store a Vector instance that is constructed with the same base type int. For example, a Vector that's constructed by calling new Vector.() can't be assigned to a variable that's declared with the Vector. data type.
Good answers from everyone. But the real answer goes a lot further. In case 1 the variable has no type and in case 2 the variable has a type. The difference is that in the second case the compiler is able to provide you with information in case something in your code goes wrong. In the first case the compiler might be able to provide some info or even no info at all in case something goes wrong in your code. If you work with untyped variables (case 1) you the developer are on your own if there's any error in your code. You'll be the one to look for them and try to fix them. In the second case the compiler will tell you where there's an error and most likely why there's an error.
In order to avoid Java exceptions I'm using Scala's exception handling class.
However, when compiling the following snippet:
import scala.util.control.Exception._
val cls = classManifest[T].erasure
// Invoke special constructor if it's available. Otherwise use default constructor.
allCatch opt cls.getConstructor(classOf[Project]) match {
case Some(con) =>
con.newInstance(project) // use constructor with one Project param
case None =>
cls.newInstance // just use default constructor
};
I receive the following error:
error: type mismatch;
[scalac] found : java.lang.reflect.Constructor[_]
[scalac] required: java.lang.reflect.Constructor[_$1(in method init)] where
type _$1(in method init)
[scalac] allCatch opt cls.getConstructor(classOf[Project]) match {
[scalac] ^
[scalac] one error found
What's going on here and how can I fix it?
I have no explanation, but a much shorter example which I hope pinpoint where the problem occurs. I think it is not related at all to exceptions, nor to reflection. Whether this behavior is an arcane but correct consequence of the specification or a bug, I have no idea.
val untypedList : List[_] = List("a", "b")
val typedList : List[String] = List("a", "b")
def uselessByName[A](a: => A) = a
def uselessByValue[A](a: A) = a
uselessByName(untypedList) fails with the same error as your code. The other combinations do not. So combination of a method with a generic call-by-name argument, called with a parameter of a generic with an existential type.
uselessByName[List[_]](untypedList) works, so I guess if you call explicitly opt[Constructor[_]] it might work too.
The type inference scheme has gotten confused by the types available--specifically, by the type of cls. If we write generic code:
def clser[A](cls: Class[A]) = allCatch opt cls.getConstructor(classOf[Project])
then it works perfectly okay. But you're probably doing something else--I can't tell what because you didn't provide the code--and this results in a mismatch between the expected and actual types.
My currently solution is to cast the constructor explicitly.
cls.getConstructor(classOf[Project]) becomes cls.getConstructor(classOf[Project]).asInstanceOf[Constructor[Project]].
I'm still wondering about the actual error and if there are better ways to resolve it -- so I'm going to leave this open.