e.g.? I've only just scratched the surface of Rust and dismissed C# as a Java clone (but maybe I shouldn't have?). What's some examples of the best of Swift that you see?
e.g.? I've only just scratched the surface of Rust and dismissed C# as a Java clone (but maybe I shouldn't have?). What's some examples of the best of Swift that you see?
Generics were a cutting-edge feature in 2005. Microsoft took the opportunity to start from scratch, and released the .Net Framework 2.0 without backwards-compatibility, and with full support for generics. A List<String> is actually a List of String.
When Sun released Java 5, they didn't want to disrupt the established Java ecosystem. Their implementation is called "type erasure". As an example, List<String> is actually just List<Object>, with automatic runtime typecasting to String. https://docs.oracle.com/javase/tutorial/java/generics/erasur...
Java's solution works well enough, but it breaks down in certain scenarios, such as multiple levels of generics. For example, when getting an element from a List<List<String>>, Object is not cast to List<String> (which doesn't really exist), but merely List.
C#'s implementation of generics became even more sophisticated with C#4, which introduced covariance and contravariance. https://msdn.microsoft.com/en-us/library/ee207183.aspx
Generics have been around since at least the early '80s.
Another interesting failed prototype on the JVM was the language "Pizza" https://en.wikipedia.org/wiki/Pizza_%28programming_language%...
https://en.wikibooks.org/wiki/Ada_Programming/Generics
http://www.cs.dartmouth.edu/reports/TR86-104.pdf
(From 1984.)
I'm not sure how this makes sense. These tags are just standard context bounds, which are extremely useful and quite awesome.
You make it sound as if these tags were some kind of special feature added to the language, or context bounds were solely invented to support these tags.
If a method needs to instantiate an object, the normal technique is to accept a factory function as a parameter. You can do the same thing with type-erased generics.
C# decided to create a shortcut for calling the constructor of a generic type parameter. But, for example, you can't call static methods of a generic type parameter (and a constructor is really just a slightly special static method).
I was already using C++ templates in 1994 with Borland C++ for Windows 3.1!
Ada, CLU and ML go back to the late 70's / early 80's.
It certainly worked at the time, for that specific compiler
C code also used to break left and right long after C90 was approved.
I had to use K&R C style code in 1999 because the HP-UX compiler at a customer location didn't knew any better, but that didn't mean other C features weren't available elsewhere.
Curious, what did you need to do specifically? Parameter declarations weren't inlined?
But anyway, C, being smaller, breaks in fewer ways
In those days HP-UX C compiler was still transitioning between K&R and ANSI standards.
We could only properly compile without strange errors while using K&R function declarations.
If memory serves me right, it was the first HP-UX release having support for 64bit file systems.
C++ templates are Turing complete, you can validate whatever you feel like at compile time.
You can write the following C++ code and C++ allows it:
<template typename T> void foo(const T& arg) { arg.bar(); }
This is perfectly fine for a macro system. But this is not how truly generic type system would work. If templates were proper generics, the typechecker would immediately refuse this to compile saying something like: "Error: I can't prove T has the bar() member."
> C++ templates are Turing complete, you can validate whatever you feel like at compile time.
So please write a template metaprogram that validates if a given C++ class (input to the program, given as a template argument) matches a table schema in the database system (the table name and connection string are also given as template arguments). For fetching the schema, you have to connect to the DB, of course at compile time. If the schema does not match, the compilation should fail ;)
Do you want an example how to write it properly?
With or without the upcoming concepts TS already in GCC 6.0?
Also this example would require T to be an interface with a bar method in C#. Do you also want to the the variant with MI and pure abstract classes in C+?
In a proper generic type system, the compiler validates it, not the programmer. Even if you constrain the type using type traits, the compiler would not check if the implementation satisfies the constraints. I can put a type trait for existence of bar() and then another programmer may rename bar() to baz() forgetting to update the constraint and the code will still compile fine.
I do admit that I need to update myself with what GCC 6.0 allows vs the letter of the TS.
template <typename T>
void foo(const T& arg) {
const Bar* b = arg;
b->bar();
}
or template <typename T>
void foo(const T& arg) {
static_assert(is_base_of<Bar, T>::value, "T must be a Bar");
arg.bar();
}
I can't say I'm a huge fan of either syntax, but the compiler will perform static type checking as if you had written where T : Bar in C#.It definitely has a downside for the development process, especially when it comes to writing libraries. But it is also to some degree inevitable if you want structural typing. Maybe there is a better way to do it though.
Further support for the idea that C++ templates are an automated copy+paste mechanism is that you're allowed to give templates arguments that are not types.
Further reading: https://msdn.microsoft.com/en-us/library/c6cyy67b.aspx
C# type checks imply a performance hit and are an implementation detail. Nothing prevents a C# compiler to choose another one. It has nothing to do with generics vs templates.
For example Modula-3 and Ada compilers use the same approach as C++ for code generation of their generics.
So where is that example of something that can only be written with C# generics, but not with C++ templates?
A github gist maybe?
That is what enable_if, type traits, if constexpr and eventually concepts allow for.
#include <string>
template <typename T>
void foo(const T& arg) {
int x = std::string("int expected");
}
$ g++ -c template.cpp
$ // see, no error
Templates are only syntax-checked. The type checker is not even executed on the non-generic code inside of templates. The type checker will be executed after the template is instantiated (expanded). At that point, generic types do not exist. There exist only concrete types.Uninstantiated templates are dead code that will be stripped anyway.
Sure, you can type-check them for particular type arguments. But you can't type-check them generally at the generic level and you have absolutely no guarantee that your library code is free of type errors. Not a problem if the goal is to produce the final executable, but a big problem for a library writer, who doesn't control the inputs (in this case: the types provided by the user of the library).
And AFAIK C++17 concepts do not address this problem, really. I can constrain my input types with them, and the calling code will be forced to conform to them (and the compiler will present a nice error message if it doesn't), but there is still no checking on the other side - that is if the template implementation is correct assuming these constraints. I can publicly declare my code requires T.bar(), then shamelessly call T.baz() in the template implementation and the compiler will not catch it.
This is like a Python program. You don't know if it type-checks before you run it, but even if you run it once or twice and it was fine, that doesn't guarantee there are no type errors.
The code line int x = std::string("int expected"); has zero relation with any of the template arguments.
So a programmer error that doesn't have anything to do with the types provided for the template.
Sure it will be caught in C#, because its build model assumes the existence of modules and everything is compiled to binary.
In C++ a similar compilation error would occur when compiling the translation unit into a library where the template is instantiated.
Of course, most templates being header only the error will only occur when instating it, but it will still blow on compilation and prevent the final generation of the exe, dll being produced.
Also errors related to semantic type check, independent of template arguments is relatively easy to achieve with unit tests.
I still fail to see how a generic system that doesn't offer partial specialization or meta-programming as being more powerful than templates.
By not doing runtime checks you get to skip that work at runtime, obviously, but you also get to enable other optimizations like inlining the monomorphised version.
Macro systems can be very powerful, but they are also quite hard to use. It is 2016 and error messages in C++ templates are still inferior to the messages you get in C#, Java or Scala generics, despite templates existing for much longer.
C++ templates are also not the very best at metaprogramming either. Take any macro system like the ones found in LISPs, Scala or Template Haskell - they are much more powerful and consistent with the rest of the language. I can code Scala metaprograms in Scala or LISP metaprograms in LISP. But I can't code C++ metaprograms in C++, I have to use this weird duck-typed functional template language which doesn't have even loops or conditionals.
I have experience in compiler design and C#, Java and C++ are my tools of trade. So I know their generics systems pretty well.
Maybe if I get bored during Easter I can bother to provide your safe list.
This sentence doesn't make much sense. Comparing oranges and apples. It is like saying Scala macros are better than Scala generics. C++ templates are neither great at metaprogramming (there are much better macro systems in other languages out there) nor great at generics (Java, C# or Swift generics are not state-of-the-art either, but in some cases I mentioned they are better).
But most importantly to me, Swift is composed in such a way that it just 'clicks' for me, ie many times many times I can guess how something is likely called or how it will behave without looking at the docs and I have a solid chance of being right - that 'intuitiveness' is something that is lacking in many other languages I've used over the years.
In regards to C#, by now it is definitely not just a Java clone anymore, in particular saner type system and much more functional features edge it for me over Java, plus the speed of evolution is much greater in the C# land. If you want to see how C# and Java differ but are tied to the JVM, try Kotlin: http://kotlinlang.org - it's fairly similar in feel to C# and has 100% Java compatibility.
IntelliJ absolutely trounces VSS and some combination of Spring Boot, DropWizard or Vert.x blows ASP.NET MVC away. Not to mention the whole ecosystem is a hell of a lot more open. There is a library for just about anything under the sun.
It gets even worse on desktops, as sysadmins might be able to isolate a server enough to allow some "new" tech, but vetting a new Java version or library for a few thousand office desktops is a task nobody really wants to do. So I wouldn't be surprised to still see some Java 1.4 Swing apps in use at big insurance or pharma companies. (And if I'd had to pick between that or do a web app that supports their IE8 browsers…)
The same thing applies to many other software packages, including browsers, Linux and Spring. Sane IA folks don't like to deploy known security holes.
It sounds like you're dealing with some backwards-thinking folk. ;-)
The alternative is auditing all your installed software packages with Java dependencies. Re-hire the agency that did that small Swing client 8 years ago. Hire someone completely new to reverse engineer another client because the original company went belly up. Ad infinitum, ad nauseam.
No wonder they'll do software cryonics.
This is getting better slightly in recent years, when you no longer have that many desktop clients and utilities, as upgrading servers is way easier than building new default images for all your desktop clients.
It definitely looks like that, but I'll take C# over Java any day
Java API looks like it was built by the worse bureaucrats they could find and one piece doesn't fit another except in a very specific (non-obvious) way