mrgriffin
I would guess for the use-case of "I have a C project and I want to run it in Fil-C" the ability for this to be a warning + run-time panic is very helpful for quickly getting started. Reminds me of GHC's -fdefer-type-errors.
I agree that I wouldn't want to deploy a program where those panics are reachable*, but it's still handy for local development and/or maybe the developer knows they aren't reachable.
I haven't checked, but I'd guess there's a warning and a -Werror -style flag to opt-in to having a hard error for unsafe assembly?
* Obviously a panic is better than not. But guaranteed safeness is better than either of those.
1. Only require that the programmer prove the variable is initialized before it's read. Riffing on Bill's example:
Object *x; // Fine
if (is_foo) {
x = &foo;
} else {
x = &bar;
}
x->a // Fine, was initialized by the time it was used.
Of course this is still a trade-off, your compiler has to work harder to prove that all paths that flow to each use are definitely-initialized. When you have initialization functions you now need to have type specifiers like 'in', 'out', and 'in/out' so that 'out' can take a pointer to uninitialized data, or something like MaybeUninit. This handles this example from Bill: Foo f;
Bar b;
grab_data(&f, &b); // Fine if 'grab_data(out Foo *, out Bar *)'.
2. Something like Rust's MaybeUninit to explicitly opt-in to wanting to deal with possibly-uninitialized data. Obviously also a trade-off, especially if you want to force all the maybe uninitialized stuff to be in an 'unsafe' block.I haven't yet digested exactly how the stacks are made to work. I think fig 8 should be obvious, but I'm getting stuck on picturing how the system guarantees that frame 1 can't grow into frame 2.
EDIT: Ah, I think I understand. It seems that they're taking advantage of a large virtual address space to give each stack loads of space, rather than them being contiguous like I assumed from fig 8.
> As modern 64-bit address-space is big enough for the allocation of many large continuous stacks [...]
To add to your point, I don't think foo can even be implemented (more accurately: is not total) because neither `Semigroup a` or `Traversable t` guarantee a way to get an `a`.
I think you'd need either `Monoid a` which has `mempty`, or `(Foldable1 t, Traversable t)` which guarantees that there's at least one `a` available.
C here is asserting that the value inside is a constant and then evaluating to that constant.
I looked at DRM/KMS briefly earlier in the year and this is what made me abandon it in the end. Can you recommend any sources of information?
The atomic API and "test only commit" both sound really useful.
Not an expert, but my gut says maybe it runs against zero values? As in, "what's the zero value for a non-nullable reference?" Maybe the answer is something like "you can only use this type for parameters", but that seems very limiting.
As for which languages allow it. I'm not sure for floats, but Pascal let you do it for ints for sure. https://wiki.freepascal.org/subrange_types
<TAB><TAB>function name(arg1, arg2,
<TAB><TAB> arg3) map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (a:as) = f a : map f as
Personally I don't see any reason to use longer names than f, a, and as because you can't add any additional information.You might say "well I don't write code like that", and I don't have any answer for you. But I find I write a fair amount of generic code.
map :: Bool -> (() -> b) -> Maybe b
map True f = Just (f ())
map False _ = Nothing
Or, in Haskell because you've got laziness you could go with: map :: Bool -> b -> Maybe b
Which already exists as a combination of Control.Monad.guard and Data.Functor.(<$). map tf b = b <$ guard tf> multiplied does not: it starts off 0, and every time it is multiplied via multiplied = multiplied * count it remains 0.
The article then goes on to use that fact for some optimizations.
readAny :: forall c r. [TypeWithReadAnd c] -> String -> (forall a. c a => a -> r) -> Maybe r
readAny types string handle
I think it's fair to say "hey, pickle doesn't require me to list all my types explicitly", but on the other hand, it's not like pickle can conjure those types out of thin air--it considers only the types that are defined in your program.Here's an example that uses Read as the serialization format and only deals with Int, Char and String; but hopefully you can imagine that I could replace the use of read with a per-type function that deserializes from a byte string or whatever.
> but even the most beautiful code is useless if it takes to long to write!
"too long"
> Tansparent
"transparent"
> visualiase
"visualize"
There are probably others, I only skimmed.
Anyway, the visualization of connecting inputs to outputs is pretty cool and I hope that it's intuitive enough to bring simple programming to more people.
if (ptr == NULL) return NULL;
for (int i = 0; i < n; ++i) dst[i] = src[i];
I particularly like it for guards at the beginning of a function, because they end up being less visually heavy, thus drawing my attention to the (presumably more business-logic-y) other lines of code.It's somewhat like how Ruby lets you write your control structure at the end of a statement to have it only apply to that statement, e.g.
return nil if ptr.nil?
And I find this style looks different enough to multiple statement control structures that I don't make the mistake of adding an additional statement without also adding brackets.Of course this is a comment about formatting code, so YMMV.
rzipWith :: (forall a. f a -> g a -> h a) -> Rec f as -> Rec g as -> Rec h as
With this type I don't think you'd be able to rearrange the elements, but you do have to pay the cost of using Const everywhere, as in you can specialize approximately my function as follows (handwavy, won't compile): zipWith :: (a -> b -> c) -> Vec n a -> Vec n b -> Vec n c
zipWith f as bs = recToVec (rzipWith f' as' bs') where
as' = vecToRec (fmap Const as)
bs' = vecToRec (fmap Const bs)
f' (Const a) (Const b) = Const (f a b)
vecToRec :: Vec n (f a) -> Rec f (Replicate n a)
recToVec :: Rec (Const a) as -> Vec (Length as) a
Rec is defined in Vinyl: https://hackage.haskell.org/package/vinyl-0.11.0/docs/Data-V...At least some of these sorts of bugs (depending on how you define "fail") are captured even in Haskell today by things like Maybe. In fact, if Haskell was total (like Idris) you wouldn't even be able to write a function that searches a list for an element with this type:
find :: (a -> Bool) -> [a] -> a
Because there's no way for you to magic an a out of nowhere in the empty list case (whereas laziness lets you use bottom). You could however write a buggy find over known non-empty lists because you could always return one of the known elements, types aren't a panacea.Dependent types go further and let you guarantee things like "zip only compiles for two lists of exactly the same length" which can be helpful in some circumstances (specifically in Haskell we use things like zip [0..] too often to want to change the function literally called zip, but you could imagine another name, perhaps zipExact as in the Safe library).
I suspect you probably already know this and meant a different kind of failure, such as mathematically invalid (which you could probably encode via a sufficiently powerful type system), or a simple misunderstanding of the requirements (which you—as the misunderstander—obviously can't).
The ecosystem exerts a lot of pressure on developers to not reinvent fundamental things, in Haskell I practically never reach for a StrictTuple or StrictEither even when I'd like strictness specifically because they are clunkier and less well integrated with other libraries.
Scala is the only language that comes to mind with this issue (scalaz vs Cats) and my impression is that even they have mostly converged.
I would say Go has much stronger idioms than either of these languages, and wouldn't need to be afraid of people inventing their own fundamental types provided they're included in the standard library.
[1] Of course we have plenty of other reasons to use it, but I digress.
Some other examples include:
- Haskell: https://hackage.haskell.org/package/ghc-justdoit
- Scala: https://github.com/TypeChecked/alphabet-soup
- Agda: https://youtu.be/3U3lV5VPmOU?t=3159
I was under the impression that justDoIt comes from Scala, but I can't find a reference for that.