Hacker Newsnew | past | comments | ask | show | jobs | submit | dgentile's commentslogin

Edited: Looks like they have safe alternatives: "

  - strlcpy() if you really just need a truncated but
    NUL-terminated string (we provide a compat version, so
    it's always available)

  - xsnprintf() if you're sure that what you're copying
    should fit

  - strbuf or xstrfmt() if you need to handle
    arbitrary-length heap-allocated strings
"


Agreed. Ownership would be way too confusing to start out with.


I think starting with a language with static typing would be better. With Python or Javascript you still need to know how the types work otherwise you can run into unexpected "defined behavior". Something like Golang makes a fair compromise between C and Python: it is statically typed, compiled, and has a garbage collector.


C++ is really nice for low-level OOP, and compared with C it adds generics and classes. Compared to Python, C++ is lower-level and can have significant performance gains with a well written program. With regard to Julia, if you write your code in "the right way", it is also compiled and low-level.


Makes sense, I can see some benefits in having more control of what happens with the memory, rather than trying to fit the model I have in mind into the datatypes python.

Found this post [0] fitting: > The best thing you can do when dealing with lower-level languages like C and C++ is understand that things like lists, strings, integers, floating point numbers, objects, etc. do not actually exist. They are simply abstractions. There are only the CPU and memory.

[0]: https://news.ycombinator.com/item?id=8356400


The problem is that fundamentally we always have types. We must define different types of bytes and the different things we can do with those bytes. If you can generate a binary from your programming language, it must use a form of static or inferred typing to know what assembly code to generate. A dynamic language just checks at runtime, and adds a bunch of overhead, which isn't always necessary, and is more likely to result in weird "defined" behavior like we get from javascript and php. Typescript is very popular because you can make certain guarantees at compile time, instead of a vague hand-wave of "the code looks good".

As an example of the benefits of type-checking, in the Vulkan api, there are a lot of handles. VkRenderPass, VkPipeline, VkSwapchain, VkDevice, etc. All of these are just pointers. If we take a function like:

    void vkDestroyCommandPool(VkDevice,VkCommandPool,const VkAllocationCallbacks*);`
And remove the type checking:

    void vkDestroyCommandPool(void*,void*,const void*);
It is the same API, but without type-checking. Even if the parameters are labelled, with this new API I could mess up and pass the wrong thing.


I don't see this as challenging anything that the article is ultimately proposing. See, for example, the last paragraph:

> I thank the flying spaghetti monster almost every day for the type system in my day job (and that is only Java’s tepid concoction)...

Isn't exactly a statement you'd expect to find in the concluding remarks an essay whose goal is to question the value of type systems or static types. It's presumably something more nuanced like that. Maybe something more like

> we are in danger of thinking that type systems are the only way of achieving correctness in software construction.

Which seems reasonable to me. Type systems are excellent for eliminating certain classes of errors. But we shouldn't let them become a golden hammer. Even if they can be used to eliminate other classes of errors, that doesn't necessarily mean they're the best tool for the job. Lately, for example, I've been seeing some disillusionment with dependent typing, and people saying, in effect, "Yeah, it's a really impressive technique, but try to find a simpler solution first."

And some of those simpler solutions do come from the dynamic programming world. For example, "You can then go further and remove the more primitive operations, only allowing access to the higher level abstractions," is another excellent way to make illegal states unrepresentable. And you don't need shiny new programming languages or rocket powered type systems to do it. I was really rather disappointed that that section of the article gave a nod to Dijkstra, but completely failed to mention Alan Kay's The Early History of Smalltalk, which was, to an approximation, several thousand words' worth of grinding away on that point.


The article is not even remotely suggesting removing type information. On the contrary, it's talking about some ways to augment a type checker with different grammar or ways of constructing APIs.


No, but you can always encode this augmented information in types to make it explicit, and possibly help the compiler make optimizations. Using a weaker type when you can use a stronger type is just as bad as removing type information.


> No, but you can always encode this augmented information in types to make it explicit

Technically yes, but not all type systems make it practical, or really relevant e.g. you can encode nullability in a type in java… but your reference to your Optional is still itself nullable.


I think it’s important to be more specific here. You can always mess up and pass the wrong thing, the type system can never know what is semantically correct, no matter how strict your types are. They’re about ergonomically reducing the space of valid programs.

There are a lot of interesting tradeoffs to be made there. Over strict specification (whether parsing or type checking), specifically checking for invariants that aren’t actually useful, can make code and systems brittle and hard to change, just like under specifying them. The specifications can also be different depending on what you’re doing with the data.

Also as the expressiveness of types increases, the space of possible ways to constrain your program space goes up, along with the complexity of the transformations of that space, making it difficult to understand what the valid program space actually is, hard to understand when you’ve accidentally excluded perfectly valid programs, etc.

So yes, fundamentally there are always types and underlying structure to useful data, but saying that it has “a” type is dramatically over-simplifying things.


>I think it’s important to be more specific here. You can always mess up and pass the wrong thing, the type system can never know what is semantically correct

This is not true. Consider the map function of a typical functional language with parametric polymorphism:

map : (a -> b) -> [a] -> [b]

That signature is complete, it covers everything there is to know about the function. And, except for trivial implementations, there is no way to implement it wrongly.

In some cases, one can even rule out trivial implementations and infer the correct implementations from the type signature alone.

In any case, there is no "semantically wrong" input to such a function. It is just a function and totally agnostic regarding your use case.


Of course that type doesn't encode everything there is to know about that function, even assuming purity.

Here are some functions that match that type signature:

    map1 foo x:xs = [foo x]

    mapR foo x:xs = append (mapR foo xs) foo x

    mapI foo x:xs = foo x : mapI foo x:xs
Of course, we can create many more functions that arrange the values in other creative ways, that add more or fewer values etc. If the function isn't pure, we can also imagine many more dimensions of functions that do arbitrarily different things from what you would expect.

If you want complete signatures without dependent types, you need functions which take only single values of different unknown types, like apply: (a -> b) -> a -> b. If you have more than one parameter of the same unknown type, you'll have some ambiguity already.

Non-dependent types can only be used to encode extremely simple properties of a program. They are certainly useful, but they are not in any way the be-all, end-all of static verification.


> Of course that type doesn't encode everything there is to know about that function, even assuming purity.

Right—we need to require foo id = id.


That only works because Haskell can't really express it. That is, if you could write Haskell code that checked that equality, that equality wouldn't be enough, because you could write a function `mapStrange foo [x]` that is equal to `map` if `foo = id` and is something else otherwise.

But since you can't compare 2 functions for equality, and you can't compare two arbitrary values for equality, then yes - your informal requirement is enough togethet with the type to force the function to be `map`.


Sorry for the confusion, I think we are using different definitions of "semantics" here, I'm not talking about formal semantics. I'm considering these to be semantically different, even though their structural types are the same:

    fn min(x: int, y: int) -> int
    fn max(x: int, y: int) -> int
The meaning of a computation changes depending on which one we use.

I probably should have used a different word than "semantics" since that has a technical definition in the PL field...


> I think it’s important to be more specific here. You can always mess up and pass the wrong thing, the type system can never know what is semantically correct, no matter how strict your types are.

Can you give an example?


  transferAmount(from: Account, to: Account, amount: Money)
How can a type system know that you are passing the accounts in the correct order?

You might start by trying to make more strict types such as SourceAccount and DestinationAccount.

  transferAmount(from: SourceAccount, to: DestinationAccount, amount: Money)
But we know that any account is likely to be both of these at different times. We only persist Accounts and have to convert at runtime. Now you face the challenge of converting a regular Account to a FromAccount.

  src := fromAccount.toSourceAccount()
  dest := toAccount.toDestinationAccount()
  transferAmount(src, dest, amt)
How can the type system know that you are converting the correct Account? The type system cannot determine what is semantically correct. It's a recursive problem.


What you are saying is all correct, but I think we disagree about the terminology. You said "the type system can never know what is semantically correct" but I think the right way of saying it is "the type system can sometimes not know what is semantically correct".

Because in practice, code like "src := fromAccount.toSourceAccount()" is very rare and happens at system boundaries or logic boundaries once - after that, all semantical errors can be caught by the typesystem, and this accounts for the vast majority of the code.

So yes, the typesystem can and will prevent semantical errors. But it can not protect you from making them in all cases, that's impossible.


A programmer will still need to write correct code, but in your first example the error happens at the boundary between two modules. In the second example, the error is fully contained within one module.

One of those two is easier to spot, either by the original programmer, or by a code reviewer, or by someone trying to track down a fault.

If all the type system does is make semantic errors easier to spot and fix, it's still offering a lot of value.


And indeed, in opengl, where all handles have the same type (GLuint), it's very easy to mix up handles of different types.

It's quite easy to fix this without breaking ABI compatibility; but it hasn't been done in any implementation that I know of.


In C perhaps that's unfortunate. I'm sure glad we have more modern C++ that would enforce pointer types.

... as long as the functions aren't declared in `extern "C" { ... }`

which many libraries are. That's for many reasons, some of which include the very type system itself being an inhibitor of easy integration across languages.


I don't quite follow. C will also prevent you from mixing up disparate pointer types; and c++ has no protection against void pointers.


> C will also prevent you from mixing up disparate pointer types

No it won't. In C++ it's a compile error [0]. In C it's just a warning [1].

> c++ has no protection against void pointers

You're somewhat correct but the answer is a lot more nuanced (because void* is very nuanced). Again, C++ will complain unless you do it "right" [2] while C is ... willing to let you blow your leg off [3]. However the definition of "right" is still just as dangerous as C's because all type information was lost in the void and it's up to the programmer to get it right -- and programmers are notoriously buggy.

[0] https://gcc.godbolt.org/z/166ns8

[1] https://gcc.godbolt.org/z/vEnajj

[2] https://gcc.godbolt.org/z/cGe39z

[3] https://gcc.godbolt.org/z/orb1s8


Using extern "C" doesn't change the C++ rules for implicit pointer conversions, though.


This exactly. That she's returning home from school at 6:30! The author didn't give their daughter's age, but we can assume it's right before 14, so maybe 12-13. I'm in high school, and I take a couple HL IB classes, school always gets out for me at 3, and then I do cross country until 5. That is already a long day. Then I go home, eat, do homework, and depending on the workload it could be anywhere between 8:00-12:00. Finally I'm able to go to bed, and redo the whole thing. I am a high schooler, and I'm taking high level classes for credits in college. The author's daughter is probably a middle schooler.

The issue is the daughter doesn't have time to be creative. I program, edit videos, etc., but all of that I have to save for the weekends. The daughter probably doesn't have the energy to be creative and just uses their phone during some downtime.

With my generation we are not always on our phones like many would believe. Pre-covid we would gather and talk after school, during lunch, in class. If I went with my friends to lunch it is acceptable to check your phone but we would never find it acceptable to be on your phone the whole time.

The issue is probably not the daughter, but the workload.


> Pre-covid we would gather and talk after school, during lunch, in class. If I went with my friends to lunch it is acceptable to check your phone but we would never find it acceptable to be on your phone the whole time.

I'm 40.

This gives me hope for our species. I lost a very good, old friend several years ago because he was constantly on his phone. Several of us were home for Thanksgiving, which is a real rarity since we live all over the United States. We were all out to dinner and he just could not get off the phone, when I finally said, "Do you think its socially unacceptable to constantly be on your phone when we're all here together??"

He got extremely defensive, and very nasty. We haven't spoken since.

I can't tell you how great it is for me to see younger people realize how important it is to be in-the-moment with the people around you.


Don't see IB mentioned often here! As an IB survivor, happy to help with CS or Physics if you run into any trouble.


From purely a programming perspective: Have they not heard of enums?


Free Software is amazing. I love emacs, Firefox, bash, zsh, nginx, postgres, llvm, linux, freebsd, and many other packages. But, I think that there are two points to be made with regard to commercial software.

1: Domain specific programs, and polish. Logic Pro X, Final Cut Pro X, Ableton, Cubase, Premier Pro, are are excellent pieces of software that people pay for and use every day. Where is the free software equivalent that isn't glitchy and has a usable, slick, ui? The more specific the case gets, and the less related to systems a Free Software project is, the less likely it is to exist or have any polish. I can list Postgres, Redis, Linux, OpenBSD, NetBSD, NodeJS, WebKit, SpiderMonkey, LLVM, GCC, Binutils, Busybox, etc., but where is the free software iMessage, Google Docs, Discord, iTunes, Steam, Google Maps, etc. There may be some of these projects out there for what I just listed, but none of them have a userbase as big as that proprietary software. The only things I can think of are VLC, Blender, and Android.

2: Free Software can only exist with Commercial Software. How many people that work in Free Software are software engineers working at a corporation? What pays for this Free Software to exist? Microsoft hosts github, big enough Free Software projects have budgets and employees at other companies paying for all of it.


High Schooler here. I've been teaching myself Vulkan and am writing a videogame, but I'm so exhausted on weekdays from my course-load that I only work on it on weekends and breaks. I wish I could put more time into it but trying to program after 6+ hours of school and then homework is a nightmare, and that code usually ends up being buggier than my normal output, with low productivity.


This is great, but I think, learning Vulkan and writing a video game can be hard within the same project. Don't burn out.

If you want a suggestion, I'd keep learning Vulkan on a side, but chose a higher-level graphics library for actually programming a game. Just to keep yourself interested and to see progress quicker. There are so many decisions and design choices in making a good game, so keeping graphics simple and small can give you more creative freedom. (If that's your final goal.)


I spent years of my precious spare time making games from junior high through college. Lost out on some social development, and made too many fan projects based on other people's IP.

I'd recommend trying to keep life balanced. If it refreshes you then enjoy. Just don't burn out on it or get stuck in perfectionism. Find that happy zone where you can feel productive or entertained or have something to share.


That's awesome - I think that would be the ideal as it pretty much replicates life after you graduate from college as a software engineer.

As the other two comments allude to, I think the keys are using it as a learning process to learn time management (i.e. avoid burn-out and over committing) and how to make it social (i.e. find other classmates to work on it with you).


1/3 and 1/3 is 1/6 ;)


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: