Live data from Hacker News

How to design a replacement for C++

apenwarr.ca

31–40 of 75 posts

Re: How to design a replacement for C++

#31
post #25

Earlier quoted context omitted.

If your language isn't completely terrible, then you can choose to use a named function anywhere an anonymous function will do. The libraries can never force you to not give your functions a name or not put them in a global context. That's why it's a harmless feature. Templates might have been harmless if there was a way to do basic obvious stuff (callback functions, strings) without using them.

I'll hazard the guess that hazzen is interpreting 'lambdas' to involve closures.

Yes and no. If a library assumes a lambda is easy, you will see a lot of code like this (using somewhat bastardized OCaml types):

  interface 'a collection {
    void sort(lt:'a -> 'a -> bool);
  }
So, if you want to use lambdas, you would get:

  foos.sort(fn x y -> x.bar() > y.bar());
And if you don't want to use lambdas, you would get:

  bool sort_by_bar_gt(x:Foo, y:Foo) {
    return x.bar() > y.bar();
  }

  foos.sort(sort_by_bar_gt);
And that is assuming you can nest functions, but chances are you will have to put that function somewhere removed from the actual call to sort. This is the exact problem the STL hits: it assumes, for many things, you want a functional style - and then it doesn't give you a way of writing lambdas. You are left with one-off functors littering your code, wishing you could write that lambda.

I would like to stress: I think lambdas are a requirement for any language, I just take issue with the argument presented to convince lambda haters.

Re: How to design a replacement for C++

#32
Sounds like Vala: reference counting instead of GC (full pointers underneath if you want), zero cost to call C, lambdas, generics, signals/properties, native unicode strings and other sugar such as foreach.

Can't do operator overloading though because they want to compile down to C without mangling names

Re: How to design a replacement for C++

#34
post #18

Earlier quoted context omitted.

I would have called it bottom heavy :) In python+C, every time something is too slow, all you have to do is push more stuff down into the C layer. You have control of the continuum between 100% optimized (100% C) and 100% clean and readable (100% python). I don't know any other programming environment that can claim that without adding tons of complication (the C/python interface layer is the simplest I've ever seen,…

Right, but the problem is that the root node is always going to be Python, and any code that uses Python is going to have to go through the root node (hence all Python code is really part of the root subtree). This becomes problematic if you have more than one queue that you're watching (e.g., input, network, graphics output, etc.). Were it possible to have Python code be in some non-root node, it'd be great (e.g., f…

In my experience, having python as the root node for multithreaded C/python programs generally doesn't present a problem. When calling into external C functions through ctypes, the GIL is released such that multithreading at the C-level is unaffected. I personally use this feature heavily to perform numerically intensive work with multiple threads as directed through python with C doing the grinding.

Additionally, all IO code in the standard library and most C-extensions that I've seen release the GIL around blocking IO calls. This allows multi-threading to be used for the standard blocking IO use cases. Further, the computationally intensive routines in numpy and scipy that I’m familiar with also release the GIL to facilitate multithreading at the C-level

The GIL only becomes an issue if you want multiple threads to be executing Python bytecode concurrently. I don’t believe this is a common problem as one rarely runs computationally intensive code at the python level. Such computationally intensive work is generally performed through C extensions or through external C functions (as accessed through ctypes). As long as such C extensions properly release the GIL, multithreading at the C-level is unaffected.

Re: How to design a replacement for C++

#35

Wow it shrunk by +1.16% http://www.tiobe.com/index.php/content/paperinfo/tpci/index.... Outstanding.

:-) One can argue about the validity of "tiobe", but still...as much as people would like to see that "C and C++ are on the decline and they're just going to get smaller," it somehow just doesn't happen. ;-)

Even in my case, I was happily coding in C# in the last 3 years, and in January - bam! - I am on another project written in, well, C++.

Re: How to design a replacement for C++

#36
post #23

Earlier quoted context omitted.

I honestly can't begin to contemplate how you expect stdio.h to work (without writing extra wrappers) if you don't support macros and a preprocessor. Some of the "functions" in there are macros.

import_c You can import C headers without your language being a superset of C.

Interesting idea, but how are you going to support "functions" like getc() that are actually macros?

Re: How to design a replacement for C++

#37
post #34
post #18

Earlier quoted context omitted.

Right, but the problem is that the root node is always going to be Python, and any code that uses Python is going to have to go through the root node (hence all Python code is really part of the root subtree). This becomes problematic if you have more than one queue that you're watching (e.g., input, network, graphics output, etc.). Were it possible to have Python code be in some non-root node, it'd be great (e.g., f…

In my experience, having python as the root node for multithreaded C/python programs generally doesn't present a problem. When calling into external C functions through ctypes, the GIL is released such that multithreading at the C-level is unaffected. I personally use this feature heavily to perform numerically intensive work with multiple threads as directed through python with C doing the grinding. Additionally, al…

These are really good points. I suppose the only problem I see is when the C modules develop their own hierarchy of types and then they have to interface with Python's hierarchy of types. That's really the only issue.

If what you're doing in C is numerical or computational in a functional way that doesn't need a hierarchy of types -- then keeping all your types in Python and calling into C for IO, computation, etc., makes a lot of sense.

Where I've run into problems is if the C modules themselves get sophisticated and start having scene graphs or hierarchies of shapes, etc. Because then it makes sense to mirror the hierarchy in Python -- but then you get real performance issues.

So I guess if you can ensure that your C modules have a clear functional interface (or at least one whose side effects are clearly defined) and doesn't involve anything but a shallow type hierarchy, then Python + C is all good for that. I.e., the C modules have to be very well-defined or have just about no 'code smell' (at least near their interface with Python). Arguably you can always do this if you make an effort to refactor your C modules. But yeah, because Python must always be at the root node, one is sort of constrained to serve the 'top', so to speak. And that may encourage a sort of top-down design which is less amenable to bottom-up programming (as mentioned in On Lisp), etc.

Re: How to design a replacement for C++

#38
ATS (ats-lang.org)

1. Can embed and call C code with no overhead, uses C representation internally

2. Embedded C can use CPP, otherwise the language has macros

3. GC is optional

4. No "system" thread

5. Optional standard library

6. Static typing, linear types, types as propositions, programs as proof.

7. ML-style exceptions, not insane

8. Examples from K&R C translated into ATS http://www.ats-lang.org/EXAMPLE/KernighanRitchie/

Re: How to design a replacement for C++

#39
post #25

Earlier quoted context omitted.

If your language isn't completely terrible, then you can choose to use a named function anywhere an anonymous function will do. The libraries can never force you to not give your functions a name or not put them in a global context. That's why it's a harmless feature. Templates might have been harmless if there was a way to do basic obvious stuff (callback functions, strings) without using them.

I'll hazard the guess that hazzen is interpreting 'lambdas' to involve closures.

Since no GC is a given, a lambda with a closure maps nicely to the C idiom of a function pointer and a void* user data parameter.

Re: How to design a replacement for C++

#40
post #23

Earlier quoted context omitted.

import_c You can import C headers without your language being a superset of C.

Interesting idea, but how are you going to support "functions" like getc() that are actually macros?

Most C libraries already implement those as both functions and macros. The macro definition usually shadows the function definition, but you can access the function version if you want, e.g. in glibc, getc() will call the macro, while (getc)() will call the function. The macro is just a wrapper for a function anyway in glibc (the internal _IO_getc), so there's no real reason to retain it except for historical reasons. If macros were eliminated in user code, you'd just use the function versions. I think having them as macros at all is an efficiency hack dating back to the days when compilers didn't do function inlining.
Post reply on HN