107

Variables (or more generally: “objects” in the sense of C) do not store their type at runtime. As far as machine code is concerned, there is only untyped memory. Instead, the operations on this data interpret the data as a specific type (e.g. as a float or as a pointer). The types are only used by the compiler. For example, we might have a struct or class ...


85

The common way to do this, at least with functional languages is to use a discriminated union. This is then a value that is one of a valid int, a value that denotes "missing" or a value that denotes "unknown". In F#, it might look something like: type Measurement = | Reading of value : int | Missing | Unknown of value : RawData A Measurement ...


58

If you do not already know what a monad is, today would be a great day to learn. I have a gentle introduction for OO programmers here: https://ericlippert.com/2013/02/21/monads-part-one/ Your scenario is a small extension to the "maybe monad", also known as Nullable<T> in C# and Optional<T> in other languages. Let's suppose you have an ...


52

The other answer explains well the technical aspect, but I'd like to add some general "how to think about machine code". The machine code after the compilation is pretty dumb, and it really just assumes that everything works as intended. Say you have a simple function like bool isEven(int i) { return i % 2 == 0; } It takes an int, and spits out a bool. ...


46

Your argumentation against floating point numbers is very fragile, probably because of naivety. (No offense here, I find your question is actually very interesting, I hope my answer will also be.) A classic argument is that floats provide a greater range, but high precision integers can meet this challenge now. For example: with modern 64-bit ...


46

You are comparing variable declarations to #defines, which is incorrect. With a #define, you create a mapping between an identifier and a snippet of source code. The C preprocessor will then literally substitute any occurrences of that identifier with the provided snippet. Writing #define FOO 40 + 2 int foos = FOO + FOO * FOO; ends up being the same thing ...


39

No, banning the builtin integer types would be absurd. They should not be abused either, however. If you need an integer that is exactly N bits wide, use std::intN_t (or std::uintN_t if you need an unsigned version). Thinking of int as a 32 bit integer and long long as a 64 bit integer is just wrong. It might happen to be like this on your current platforms ...


27

The same reason I don't drive a truck when going to work. I don't use something that I won't use the features of. First of all an array is a primitive construct so an array is faster and more efficient than a List<> for sure, so your argument is not true. Array is also available everywhere and known by developers using different languages and platforms. ...


26

Because switching to integers doesn't solve anything. The problem with floats isn't that they have inaccuracies, it's that half the people using them don't pay any attention to what's going on. Those same people aren't going to pay proper attention to the units they are using when they use an integer, and a different set of screw ups will happen. Repeat ...


24

Yes, definitely. Functions/methods that take too many arguments is a code smell, and indicates at least one of the following: The function/method is doing too many things at once The function/method requires access to that many things because it's asking, not telling or violating some OO design law The arguments are actually closely related If the last one ...


24

First: plain text is binary (it's not even the UTF8 or ASCII characters "0" and "1" but actual on/off bits) That said, some of the reasons are: Business/design constraints: allowing the number 7626355112 in the HEIGHT column of the PERSON table would be wrong. Allowing "Howya" in the DATE column of an INVOICE would be wrong. Less error prone code: you don'...


22

TLDR; Remove null properties The first thing to bear in mind is that applications at their edges are not object-oriented (nor functional if programming in that paradigm). The JSON that you receive is not an object and should not be treated as such. It's just structured data which may (or may not) convert into an object. In general, no incoming JSON should ...


21

Physical characteristics of the universe (like the number of atoms in it) are not useful to determine the boundaries of number sizes, because useful calculations exist using numbers having wider ranges. Floating point numbers are a tradeoff between accuracy and range. They deliberately give up some accuracy to achieve greater range.


19

You need arrays to manage your collection of mutable structs, of course, and what would we do without those. struct EvilMutableStruct { public double X; } // don't do this EvilMutableStruct[] myArray = new EvilMutableStruct[1]; myArray[0] = new EvilMutableStruct() myArray[0].X = 1; // works, this modifies the original struct List<EvilMutableStruct> ...


18

The only reason I would use long today is when calling or implementing an external interface that uses it. As you say in your post short and int have reasonably stable characteristics across all major desktop/server/mobile platforms today and I see no reason for that to change in the foreseeable future. So I see little reason to avoid them in general. ...


18

I think that in this case a variation on a Null Object Pattern would be useful: public class Measurement { private int value; private bool isUnknown = false; private bool isMissing = false; private Measurement() { } public Measurement(int value) { this.value = value; } public int Value { get { if (!isUnknown &...


17

Interfaces don't describe behaviour. Quite the opposite, sometimes. Interfaces describe contracts, such as "if I am to offer this object to any method that accepts an ISummarizableEntity, this object must be an entity that is able to summarize itself" -- in your case, that is defined as being able to return a string ID and a string Description. That's a ...


17

Like so many aspects of language design, it comes to a trade-off of elegance against performance (not to mention some historical influence from earlier languages). Alternatives It is certainly possible (and quite simple) to make a programming language that has just a single type of natural numbers nat. Almost all programming languages used for academic ...


16

Well, first off, type inference has nothing to do with the maturity of the runtime, whether that runtime is a 30 year old CPU or a VM that is so new the bits are still shiny. it's all about the compiler. That said, it is allowed for generics, the reason why it's not allowed for non-generic types seems to be because of philosophy -- there's nothing ...


16

Java's exception handing mechanism uses the class hierarchy to model a taxonomy of exception cases. Catch phrases effectively do instanceof tests. Thus they can distinguish ClosedByInterruptException from more general cases AsynchronousCloseException, ClosedChannelException, etc. Throwable#toString() includes the class name. Thus the stack traceback shows ...


15

So why would I ever want to use an array? Rarely, you will have a scenario where you know that you need a fixed number of elements. From a design perspective, this should be avoided. If you need 3 things, the nature of business means that you'll very often need 4 in the next release. Still, when this rare scenario actually occurs, using an array to enforce ...


15

First of all, let's get one thing out of the way: birthdays are one thing, dates-of-birth are another. A Birthday is an exotic data type because it lacks not only the components of hours, minutes etc but it also lacks the year component. If you really want to deal with birthdays, I would recommend inventing your own data type which contains nothing but a ...


15

Update: I have edited the answer a little bit, because it may have lead to confusion. Going with an empty string is a definitive no. Empty string still is a value, it is just empty. No value should be indicated using a construct which represents nothing, null. From API developer's point of view, there exist only two types of properties: required (these ...


14

There are a lot of strong opinions surrounding the debate but obviously this isn’t actually a matter of opinion, it’s a matter of facts. So we should look at empirical research. And the evidence from that is clear: Yes, static typing is worth the trade-offs — and not just by a bit, but in fact substantially. In fact, solid evidence shows that static typing ...


14

Alright, let's go one by one. Values Values are the concrete pieces of data that programs evaluate and juggle. Nothing fancy, some examples might be 1 true "fizz buzz foo bar" Types A nice description for a type is "a classifier for a value". A type is a little bit of information about what that value will be at runtime, but indicated at compile time. ...


14

If you literally MUST use an integer then there is only one possible solution. Use some of the possible values as 'magic numbers' that mean 'missing' and 'unknown' eg 2,147,483,647 and 2,147,483,646 If you just need the int for 'real' measurements, then create a more complicated data structure class Measurement { public bool IsEmpty; public bool ...


13

As Amon pointed out, this is a good application for the visitor pattern. Using it, your AI classes will end up looking something like this: void decide(HomeSquare square); void decide(WorkSquare square); void decide(ShopSquare square); And your squares have an accept function that looks like: void accept(AI ai) { ai.decide(this); } That lets you use ...


Only top voted, non community-wiki answers of a minimum length are eligible