http://www.jesperdj.com/2015/10/12/project-valhalla-generic-...
> Finalization. Finalization makes no sense for values and should be disallowed (though values may hold reference-typed components that are themselves finalizable.)
This is a little disappointing. I was hoping that the lifetime of essentially stack based variables could be tracked, and finalization could be bound to the stack. That would be really powerful; though mind bending after beating so many Devs to not rely on finalization.
Imagine wrapping a Closable object in a Closing tuple for instance, and that is guaranteed to run when the tuple goes out of scope.
Of course, since value types are immutable, that would be a bit memory wasteful I guess.
I guess it doesn't typically make sense to capture a RAII object and have the copy outlive the original, but it also may not make sense to delay the lifecycle of the original since it breaks the expectation of "i put this on the stack, so expect it to finalize when it goes out of scope". Probably best not to mix the two. That is, a stack-allocated RAII object whose finalizer is called when it goes out of scope, which references some data that can be closed over, with a lifetime separate from the RAII object.
At the very least, you would call finalizers on both (the stack one when it goes out of scope and the copy when it gets garbage collected) and then its up to the programmer to make sure that shared resources are finalized correctly (eg by keeping a shared reference count...). (I'm thinking a use case where the object represents some external resource that should be freed only once)
Sounds pretty error prone though.
I suppose that Java's solution is KISS: simply don't support finalizers on value objects.
Edit: I'll add that it's possible that the proper implementation for even a bog-standard, assign-to-a-variable copying would need to work this way (make another finalization-delaying handle) but I think that's less-certainly true.
I did notice one point that struck me as odd (under "Details, details"):
> Can a value class implement interfaces? Yes. Boxing may occur when we treat a value as an interface instance.
I don't normally think of values in other languages as having methods directly or an interface like this. I wonder what the primary reasons for this would be. Backwards compatibility might be one reason.
[1] https://blogs.msdn.microsoft.com/abhinaba/2005/10/05/c-struc...
If I understand you correctly, Haskell has this, and it's basically all you have to implement generic interfaces in Haskell.
A simple example is the Bounded class, whose interface exposes two functions: minBound and maxBound. So, for example, all integers (int8, uint8, int16, uint16, [...], uint64) have upper and lower bounds, and can implement this interface, like so (Word8 is uint8):
instance Bounded Word8 where
minBound = 0
maxBound = 255
This forces all instances of a class to be a type that contains all information needed to implement the interface (as opposed to some construct that needs to accumulate state at runtime in order for it to work properly), which means the compiler can check almost everything at compile-time.This is where monads come in, which is simply a value that describes a computation, e.g. fetching a value of a specific type from a web server at a given URL. So, in Haskell, all that exists are values, and they're also used to represent an operation which, at runtime, performs a certain action.
So, for example, the following function:
concatStr :: String -> String -> String
is a pure function which only modifies it's two arguments (String and String) and produces a String, whereas printReadStdIn :: String -> IO String
printReadStdIn str = do
putStrLn str
getLine
is a function which, when given a String, will -- at runtime -- print out a String and read a String from standard input, and this String will be available inside the IO monad (which can implement interfaces, because it's just a value).