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

Fundamentally, CPUs use 0-based addresses. That's unavoidable.

We can't choose to switch to 1-based indexing - either we use 0-based everywhere, or a mixture of 0-based and 1-based. Given the prevalence of off-by-one errors, I think the most important thing is to be consistent.


The reason many languages prefer `length` to `count`, I think, is that the former is clearly a noun and the latter could be a verb. `length` feels like a simple property of a container whereas `count` could be an algorithm.

`countof` removes the verb possibility - but that means that a preference for `countof` over `lengthof` isn't necessarily a preference for `count` over `length`.


But count is more clearly a dimensionless number of elements, and not a size measured in some unit (e.g. bytes).

I tend to use numFoos (short for “number of foos”), and only use fooCount when the variable is used for actual counting (like an errorCount variable that is incremented for each error).

Countof is strange, because one doesn’t talk about the “count of something” in English, other than uses like “on the count of three” (or the “count of Monte Cristo” ;)).


At least one of them is wrong


Yeah, you could argue that choosing C is just choosing a particular subset of C++.

The main difference from choosing a different subset, e.g. “Google C++” (i.e. writing C++ according to the Google style guide), is that the compiler enforces that you stick to the subset.


C's string handling is so abominably terrible that sometimes all people really need is "C with std::string".

Oh, and smart pointers too.

And hash maps.

Vectors too while we're at it.

I think that's it.


When I developed D, a major priority was string handling. I was inspired by Basic, which had very straightforward, natural strings. The goal was to be as good as Basic strings.

And it wasn't hard to achieve. The idea was to use length delimited strings rather than 0 terminated. This meant that slices of strings being strings is a superpower. No more did one have to constantly allocate memory for a slice, and then keep track of that memory.

Length-delimited also super speeded string manipulation. One no longer had to scan a string to find its length. This is a big deal for memory caching.

Static strings are length delimited too, but also have a 0 at the end, which makes it easy to pass string literals to C functions like printf. And, of course, you can append a 0 to a string anytime.


Just want to off-topic-nerd-out for a second and thank you for Empire.


You're welcome!

One of the fun things about Empire is one isn't out to save humanity, but to conquer! Hahahaha.

BTW, one of my friends is using ClodCode to generate an Empire clone by feeding it the manual. Lots of fun!


I agree on the former two (std::string and smart pointers) because they can't be nicely implemented without some help from the language itself.

The latter two (hash maps and vectors), though, are just compound data types that can be built on top of standard C. All it would need is to agree on a new common library, more modern than the one designed in the 70s.


I think a vec is important for the same reason a string is… because being able to properly get the length, and standardized ways to push/pop from them that don’t require manual bounds checking and calls to realloc.

Hash maps are mostly only important because everyone ought to standardize on a way of hashing keys.

But I suppose they can both be “bring your own”… to me it’s more that these types are so fundamental and so “table stakes” that having one base implementation of them guaranteed by the language’s standard lib is important.


why not std::string?


You can surely create a std::string-like type in C, call it "newstring", and write functions that accept and return newstrings, and re-implement the whole standard library to work with newstrings, from printf() onwards. But you'll never have the comfort of newstring literals. The nice syntax with quotes is tied to zero-terminated strings. Of course you can litter your code with preprocessor macros, but it's inelegant and brittle.


Because C wants to run on bare metal, an allocating type like C++ std::string (or Rust's String) isn't affordable for what you mean here.

I think you want the string slice reference type, what C++ called std::string_view and Rust calls &str. This type is just two facts about some text, where it is in memory and how long it is (or equivalently where it ends, storing the length is often in practice slightly faster in real machines so if you're making a new one do that)

In C++ this is maybe non-obvious because it took until 2020 for C++ to get this type - WG21 are crazy, but this is the type you actually want as a fundamental, not an allocating type like std::string.

Alternatively, if you're not yet ready to accept that all text should use UTF-8 encoding, -- and maybe C isn't ready for that yet - you don't want this type you just want byte slice references, Rust's &[u8] or C++ std::span<char>



If only WG14 added something similar to C.

Yes, SDS exists, however vocabulary types are quite relevant for adoption at scale.


It's a class, so it doesn't work in C.


Sure, but you can have a similar string abstraction in C. What would you miss? The overloaded operators?


Automatic memory accounting — construct/copy/destruct. You can't abstract these in C. You always have to call i_copied_the_string(&string) after copying the string and you always have to call the_string_is_out_of_scope_now(&string) just before it goes out of scope


This seems orthogonal to std::string. People who pick C do not want automatic memory management, but might want better strings.


Automatic memory management is literally what makes them better


For many string operations such as appending, inserting, overwriting etc. the memory management can be made automatic as well in C, and I think this is the main advantage. Just automatic free at scope end does not work (without extensions).


You can make strings (or bignums or matrices) more convenient than the C default but you can never make them as convenient as ints, while in C++ you can.


Yes, but I do not think this is a good thing. A programming language has to fulfill many requirements, and convenience for the programmer is not the most important.


Empirically it is. All the most used languages are the most convenient ones.


The C++ std::string is both very complicated mechanically and underspecified, which is why Raymond Chen's article about std::string has to explain three different types (one for each of the three popular C++ stdlib implementations) and still got some details wrong resulting in a cycle of corrections.

So that wouldn't really fit C very well and I'd suggest that Rust's String, which is essentially just Vec<u8> plus a promise that this is a UTF-8 encoded string, is closer.



Yeah, WG14 has had enough time to provide safer alternatives for string and arrays in C, but that isn't a priority, apparently.


Add concurrency and you more or less came up with same list C's own creator came up when he started working on a new language.


And constructors and destructors to be able to use those vectors and hash maps properly without worrying about memory leaks.

And const references.

And lambdas.


C is not a subset of C++, there are some subtle things you can do in C that are not valid C++


It is when compared with C89, also the ISO C++ requires inclusion of ISO C standard library.

The differences are the usual that occur with guest languages, in this case the origin being UNIX and C at Bell Labs, eventually each platform goes its own merry way and compatibility slowly falls apart with newer versions.

In regards to C89 the main differences are struct and unions naming rules, () means void instead of anything goes, ?: precedent rules, implicit casts scenarios are reduced like from void pointers.


Some subtle and some not so subtle.


Linters etc... Validates the subset you're choosing to use for your project too.


There’s also CimGUI. I know the underlying C++ library is well-regarded - I’m curious to hear people’s experiences using the C wrapper.

https://github.com/cimgui/cimgui


> statically-typed

> Embed/extend in C

Is Lily intended to be (or could it be used as) a statically-typed alternative to Lua?

Personally I'm happy with dynamic typing for scripting - but I suspect many people would welcome a statically-typed option, and there don't seem to be many available.


Many of us would love a TypeScript analogy for Lua.

There have been some attempts:

Luau (5.2k, last week, https://luau.org/, https://github.com/edubart/nelua-lang)

Nelua (2.3k, 8 months ago, https://nelua.io/, https://github.com/luau-lang/luau)

Terra (2.9k, 3 days ago, https://terralang.org/, https://github.com/terralang/terra)

Teal (2.7k, 2 days ago, https://teal-language.org/, https://github.com/teal-language/tl)

The Luau author is always on the official Lua mailing list, and it has twice as many stars, so it seems likely to win the long term popularity contest.


Note that some of those can't run on a regular Lua runtime.

Luau is a separate implementation of a Lua dialect. However, it's backed by Roblox and being increasingly used in high budget games such as Alan Wake 2, and tools like Rive.

And Terra is more of a low-level language embedded in regular Lua for metaprogramming, than a statically-typed Lua.

In this vein there's also Pallene, which integrates better with regular Lua on a slightly-patched Lua runtime.

https://github.com/pallene-lang/pallene

(BTW the links for Nelua and Luau repos got mixed.)


Also it looks like[1] Luau is the official Roblox Studio scripting language, and is baed on Lua 5.1 (possibly LuaJIT?) which means it's behind mainstream Lua.

Not sure which Lua versions the others are based on.

[1] https://create.roblox.com/docs/luau



Maybe it's time we had some sort of flag next to the post headline as this question comes up every single time a post gets a second life.


Agreed! I knew about the second chance pool but didn't realize it reset all the timestamps.


> You basically need two pieces of state

That’s enough for INDENT, but for DEDENT you also need a stack of previous indentation levels. That’s how, when the amount of indentation decreases, you know how many DEDENTs to emit.

The requirement for a stack means that Python’s lexical grammar is not regular.


AFAICT Python basically is a [statically-]typed language nowadays. Most people are using MyPy or an alternative typechecker, and the community frowns on those who aren’t.


> Most people are using MyPy or an alternative typechecker, and the community frowns on those who aren’t.

That's not like a widespread/by-default/de-facto standard across the ecosystem, by a wide margin. Browse popular/trending Python repositories and GitHub sometime and I guess you can see.

Most of the AI stuff released is still basically using conda or pip for dependencies, more times than not, they don't even share/say what Python version they used. It's basically still the wild west out there.

Never had anyone "frown" towards me for not using MyPy or any typechecker either, although I get plenty of that from TS fans when I refuse to adopt TS.


I think in the case of TS, it's more that JavaScript itself is notoriously trash (I'm not being subjective; see https://www.destroyallsoftware.com/talks/wat), and TypeScript helps paper over like 90% of the holes in JavaScript.

Python typed or untyped feels like a taste / flexibility / prototyping tradeoff; TypeScript vs. JavaScript feels like "Do you want to get work done or do you want to wrap barbed wire around your ankle and pull?" And I say this as someone who will happily grab JS sometimes (for <1,000 LOC projects that I don't plan to maintain indefinitely or share with other people).

Plus, TypeScript isn't a strict superset of JavaScript, so choice at the beginning matters; if you start in JS and decide to use TS later, you're going to have to port your code.


Typed Python vs untyped Python is literally the same as TS vs JS, don't let others fool you into thinking somehow it's different.

> TypeScript helps paper over like 90% of the holes in JavaScript

Always kind of baffles me when people say this, how are you actually programming where 90% of the errors/bugs you have are related to types and other things TS addresses? I must be doing something very different when writing JS because while those things happen sometime (once or twice a year maybe?), 90% of the issues I have while programming are domain/logic bugs, and wouldn't be solved by TS in any way.


I mean, I'm one of the fools who would fool you into thinking it's different, since I use all four languages. ;)

I can just skip the mypy run if I want to do untyped Python. I can't skip adding types if I'm writing TypeScript in most contexts; it's not valid TypeScript syntax. Conversely, I can't add types to JavaScript; it's not valid JavaScript syntax (jsdoc tags and running a static checker over that being a different subject, and more akin to the Python situation).

> how are you actually programming where 90% of the errors/bugs you have are related to types and other things TS addresses

It's the things in the "wat" video. JavaScript, in general, errs on the side of giving you some answer when you try and do something very unusual with types (like add a boolean to a number or a string to an array) over taking a runtime error. TypeScript will fail to typecheck in most of the places where those operations are techincally correct but surprising as hell in the wrong way unless you explicitly coerce the types to match up.


> It's the things in the "wat" video.

It's a funny video, still after 15 years of seeing it, I'll give you that. But the number of times I'm bothered by accidentally triggering those scenarios in real-life? Could probably count that on one hand.

I also give you that TypeScript helps beginner JavaScript developers a ton, and that's no easy feat by itself, just because of those things you mention. Once you build up intuition about how things work in JavaScript though, those sort of bugs should stop happening though, otherwise I'd say you aren't really learning the language.


> Never had anyone "frown" towards me for not using MyPy or any typechecker either

I’ve seen it many times. Here’s one of the more extreme examples, a highly-upvoted comment that describes not using type hints as “catastrophically unprofessional”:

https://www.reddit.com/r/Python/comments/1iqytkf/python_type...


But yeah, that's reddit, people/bots rejoice over anything being cargoculted there, and you really can't take any upvote/downvote numbers on reddit seriously, it's all manipulated today.

Don't read stuff on reddit and use whatever you've "learned" there elsewhere, because it's basically run by moderators who try to profit of their communities these days, hardly any humans left on the subreddits.

Edit: I really can't stress this enough, don't use upvotes/likes/stars/whatever as an indicator that a person on the internet is right and has a good point, especially not on reddit but I would advice people to not do so on HN either, or any other place. But again, especially on reddit, the upvotes literally count for nothing. Don't pick up advice based on upvoted comments on reddit!


Generally you only get frowned at if you're not using type hints while contributing to a project whose coding standards say "we use type hints here."

If you're working on a project that doesn't use type hints, there's also plenty of frowning, but that's just because coding without a type checker is kind of painful.


> Generally you only get frowned at if you're not using type hints while contributing to a project whose coding standards say "we use type hints here."

Yeah, that obviously makes sense, not following the code guidelines of a project should be frowned upon.


It's a pretty nice best-of-both-worlds arrangement. The type information is there, but the program still runs without it (unless one is doing something really fancy, since it does actually make a runtime construct that can be introspected; some ORMs use the static type data to figure out database-to-object bindings). So you can go without types for prototyping, and then when you're happy with your prototype you can let mypy beat you up until the types are sound. There is a small nonzero cost to using the types at runtime (since they do create metadata that doesn't get dropped like in most languages with a static compilation step, like C++ or TypeScript).

I can name an absolute handful of languages I've used that have that flexibility. Common LISP comes to mind. But in general you get one or the other option.


> It's a pretty nice best-of-both-worlds arrangement

It’s also a worst-of-both-worlds arrangement, in that you have to do the extra work to satisfy the type checker but don’t get the benefits of a compiled language in terms of performance and ease-of-deployment, and only partial benefits in terms of correctness (because the type system is unsound).

AFAIK the Dart team felt this way about optional typing in Dart 1.x, which is why they changed to sound static typing for Dart 2.


Without dependent typing, it's the worst of all worlds anyway. You have to express types, but they aren't expressive enough to not have to also express the same in tests, leaving this weird place where you have to repeat yourself over and over.

That was an okay tradeoff for humans writing code as it enables things like the squiggly line as you type for basic mistakes, automatic refactoring, etc. But that stuff makes no difference to LLMs.


> you need to [use Git] to work with everyone else

Programmers use different operating systems, editors, languages - is there any reason we all have to use the same source control tool? We weren’t doing so before Git came along.


You could make that argument about HTTP, SMTP, Slack, or the English language. It turns out that yes, the actual concrete points of collaborative interaction do need to be standardised to a degree, unless you're thinking of everyone shouting into their particularly flavoured void, with no means of communicating. You can have different clients speaking the same protocol, but you can't have different protocols.

Even before git, you generally had to use what your team was using, or the FOSS project you were trying to contribute to. So it's kind of a moot point.


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

Search: