I want to make a few observations about this, and why I found it seemingly less "hacky" than other such attempts:
- As I said in an earlier comment, "var" is just a typedef'd "void *". The downside is that libCello code is essentially untyped, but the upsides are that the C preprocessor is now enough to do the processing needed for the rest of the macros in the language, and that you can still mix regular typed C with libCello code for a "best of both worlds" mix.
- Looks pretty, right? What you're responding to is not just the nice non-capitalized macros and the $ keyword, but the syntax highlighting in his examples. Fire up a text editor and write you some libCello code without this highlighting and it probably won't feel as nice.
I'm extremely interested in the idea of taking the syntax highlighting, formatting, and code completion OUT of these specialized IDEs and plugins and into some kind of standard "bidirectional channel" between a language processor or compiler, its macro system, and the user's editor of choice.
We should be able to make entire DSLs and specialized syntaxes that not only compile, but are able to provide rich information to the surrounding development environment in a standardized way. I'm not alone on this. F#'s Type Providers do exactly that. But imagine being able to control not only the "intellisense", but also the syntax highlighting, argument/return tooltips, documentation, preferred formatting, snippets, etc.
And by "surrounding development environment" I mean everything from the command line to vim and emacs all the way to Sublime Text, Eclipse, and Visual Studio. Even github! Why do you have to register a new syntax highlighter on github for a language and hope they turn it on?
> I'm extremely interested in the idea of taking the syntax highlighting, formatting, and code completion OUT of these specialized IDEs and plugins and into some kind of standard "bidirectional channel" between a language processor or compiler, its macro system, and the user's editor of choice.
Well maybe if we stopped using ASCII files as our source code and used a richer type of document we could start to make some improvements!
What kind of rich document? Well, what about HTML? Did you know you can even embed interactive elements in such documents? What if we started embedding our source code and editors in our documents instead of the other way around? The whole model is inverted, but mainly for historical reasons, because you know, in 1979 all we had was VT100 to interface with our machines... it's like we never moved on... why is my "code" a splattering of ASCII files in a directory? A package definition, tests, dotfiles for this and for that... ship the editor, the tests, the docs, the examples, and the source ALL as one document!
Author here. Yeah the syntax looks much better with correct highlighting. I've provided a custom definition for Notepad++ on the repo - and of course there is the definition used on the website too.
I'm also a big fan of DSLs and would love see some of the things you mention. My next (fun) big project is actually not so far from the same lines ;)
Many thanks to everyone for the kind comments! It really is encouraging. :)
Super stuff this, that's a very interesting approach.
I spent the better part of the last two years writing a (closed source, sorry) library that does some of this, and some other stuff besides (state machines, events, 'proper' strings with automatic garbage collection and allocation, message passing).
Maintaining static typing was a big pre-requisite for that library, without it too much of value would be lost to offset the gains. It was a very educational project for me, it definitely re-inforced the 'half of common lisp' meme.
To program a piece of software using that library no longer felt like programming in C, every now and then you'd see a bit of C shine through in the lower level code. The whole thing relied to a ridiculous degree on macro cleverness (something to be avoided, for sure) and other deep knowledge of how C works under the hood to get certain effects, and I found this part of it less than elegant (even if the results were quite a big step up from programming in C).
The main justification for doing all this was to straighten out a project that had become bogged down under increasing complexity and a failure to abstract out the common elements. Choosing C for this project was a poor decision but since there was not going to be any budging on that front I tried to make the job work out as good as possible.
It's quite interesting to see how far you can push C but at the same time you really have to ask yourself if you are on the right road if you find yourself doing things in such a manner.
Like Cello, the lib I wrote is a way to force the language to become another language, which always has drawbacks in terms of unintended side effects and long term support.
Probably better to switch to a platform that is closer to your problem domain (in this case, such as erlang, clojure or even go), as much as I liked tinkering with C it felt like we were making life harder than it needed to be.
I'm looking for standards / set of libraries / best practices for "modern" C development, but I've yet to find a comprehensive resource.
Stuff like typedefing a manual fixed sized int type to be cross-platform compatible, that books don't really tell you to do but are important and come up often.
I'd be okay with a small, well written example library too. Does anyone happen to know something like this?
edit: Ah, sorry if I misled you, that was just an example of the kind of tips and pointers I was looking for. Or weird bits like the linux kernel list_head. http://kernelnewbies.org/FAQ/LinkedLists Or common libraries like bstring that make life easy. Or even a single, comprehensive implementation of good data structures, since everyone seems to have their own vector.h and/or hash.h that fails to cover much other than their own use case.
You may want to study the source code of a well-written, modern C project like git: https://github.com/git/git
The fixed-size int finally got a permanent solution: #include <stdint.h>
If you are targeting autoconf/automake as your build system, that has a lot of built-in solutions to portability issues, like defining macros. It's not easy to learn, and I don't pretend to know it well, but when I'm compiling someone else's project, I'm always happy to see a configure script.
What I find annoying about libraries like glib is that they tend to impose their own style on your project by using their own typedef'ed types and such.
If you don't mind it, you can cobble together your own data structures from various open-source projects. Judy arrays are pretty fast, and you can use them in a variety of ways. Searching google for "c hash table" came up with a lot of excellent results, so try googling whatever data structure or algorithm you need, and chances are, you'll find something.
Glib/GObject is pretty good and seems to be what you're looking for: https://developer.gnome.org/glib/2.37/ It's not tied to the GNOME platform at all but rather contains building blocks such as hash maps, linked and array lists, heap allocators, string manipulation functions and so on. Personally, I find some parts of GObject to be over engineered and distasteful but most of it is solid utility.
Then you have https://wiki.gnome.org/Vala which is a whole new language built on top of C + Glib/Object whose main selling point is that it compiles to, and is totally compatible with, plain C code.
Do keep in mind that all of this, Glib, Vala, Cello and other "make C more like a high-level language" are basically hacks to workaround the fact that C is a very low-level language and lacks many powerful features. I believe one is much more productive using Glib + C than just plain C, but you are still less productive than if you had choosen a modern language in the first place.
As somebody with the same query, let me hop on - how does "Learn C the hard way" fare? I've got it mentally bookmarked the for next time I touch C code.
I'm a fan of BSD sys/queue.h and especially sys/tree.h; they are liberally-licensed header-only implementations of various kinds of linked lists resp. binary trees.
Wow, this is an impressive amount of high-level feel for relatively little preprocessor code (and a fairly lightweight C library underneath that). Holds together pretty consistently, which is hard to do with syntax extensions built on top of the C preprocessor, vs in languages with more convenient syntax-extension or macro systems.
I spent the last hour trying to get the example programs on the front page of the libCello site to compile on OS X (10.8.4). I discovered I was missing some include flags. This is what finally worked:
$ gcc -lCello -std=c99 -fnested-functions example.c -o example
Note that "var" is a typedef'd "void *". This essentially bypasses C's typechecker for libCello code. The author admits as such, and maybe that's just fine for what you need to do, but you should be aware of it.
I wrote a similarly-themed (although much less complete and much less useful) package for Go called 'Proto' which essentially sidesteps the static typechecker by mapping the 'base useful type' to `interface{}`, which is philosophically similar to `void *`.
I personally have no problem with it (other than the syntax needed to unbox/rebox values). I find that having the freedom to use a type system or not a very compelling feature in a language.
That being said, I understand why it might sit very poorly with some.
random question: doesn't ObjC define 'nil' (or self?) as 'void*'? I did some ObjC coding 2 years ago and I remember seeing something like this and thinking: oh boy.
After looking at the source, this appears to be a great beginners resource of how to build on top of C. The source is very concise and straightforward. I'm curious to see what will come from this.
People interested in real-world high(er)-level C programming should take a look at this book, "especially the class methodology in Chapter 4": http://www.duckware.com/bugfreec/index.html
Side note: this book would certainly be down-voted on r/programming but I expect more grown-ups here.
An interesting experiment, but even as the author states "it's a fun experiment". It makes things easier to read & understand for beginners, maybe, but he even states that it's not for beginners. If I have to be a C power user to use it, I imagine I'd feel more comfortable without it. Just my opinion though.
I think quite similar about this, its in some way like training wheels on a motorcycle.
But I think there could be quite interesting uses for Cello, namely you do your prototyping with it and then you trow out the library and refactor the code to pure C.
What is this? It claims to be a (GNU99) C library, but I don't see how this can be the case, considering all the non-C constructs in the sample code ($(), try/catch, foreach). So it this just a language of its own that is compiled into C?
$ is a valid function name according to gcc. try/catch/foreach are #define'd as part of it. As an example, foreach is defined to a for loop over an iterator, which is any Cello class with a couple of functions defined.
I'm guessing that the GNU99 qualification is important. GCC supports most if not all of the claimed features, or at least the low-level constructs required to create them.
This is the kind of functionality that D language is really good at. If I were to go beyond the fun bit of this project, i would have a look at D language.
I think it's more useful than D though, because I can just add a header file to an old C project and make things better and still have things interoperate.
Chello is nice proof of concept, but personally i'd like to see only one or two changes to C standard:
1. sizeof(function) -> would give user ability to copy functions around.
2. maybe new reserved keyword _Func -> function tagged with _Func would indicate that function must be compiled as function object (defined sizeof) and compiler needs to address fact that function may be moved around and used (relative addressing and i guess bunch or others problems that would arise). Only code, nothing to do with ELF or other formats.
Another interesting thing to do would be to, somehow, eliminate function pointers with _Func.
In any case, user would be responsible for creating environment for that (lambda?) functions, like manually setting mprotect or setting up stack (prologue.h & epilogue.h ???).
This looks very nice indeed. The main thing that will interfere with usability for me as a non-C guru is the lack of thread support. But I am really grateful for the effort since my "spiritual home" among programming languages is definitely the dynamic languages, yet I appreciate the need and beauty of C in many instances when performance is necessary. libcello's apparent optional static typing (the "var") is really nice -- it's one of the wonderful things about using Cython alongside Python.
So, because I am a nub in this stuff... When it says C library, does that mean anything that works with C (say a gui library for example GTK) will work perfectly fine with this? I would just change the syntax as required and call it good?
You can write regular C GTK+ code side by side with it, but you would need a wrapper in order to use most of the constructs with GTK+, or anything else not written with Cello's type system in mind (e.g. var w = $(GTKWidget) would not work for multiple reasons).
[+] [-] breckinloggins|12 years ago|reply
- As I said in an earlier comment, "var" is just a typedef'd "void *". The downside is that libCello code is essentially untyped, but the upsides are that the C preprocessor is now enough to do the processing needed for the rest of the macros in the language, and that you can still mix regular typed C with libCello code for a "best of both worlds" mix.
- Looks pretty, right? What you're responding to is not just the nice non-capitalized macros and the $ keyword, but the syntax highlighting in his examples. Fire up a text editor and write you some libCello code without this highlighting and it probably won't feel as nice.
I'm extremely interested in the idea of taking the syntax highlighting, formatting, and code completion OUT of these specialized IDEs and plugins and into some kind of standard "bidirectional channel" between a language processor or compiler, its macro system, and the user's editor of choice.
We should be able to make entire DSLs and specialized syntaxes that not only compile, but are able to provide rich information to the surrounding development environment in a standardized way. I'm not alone on this. F#'s Type Providers do exactly that. But imagine being able to control not only the "intellisense", but also the syntax highlighting, argument/return tooltips, documentation, preferred formatting, snippets, etc.
And by "surrounding development environment" I mean everything from the command line to vim and emacs all the way to Sublime Text, Eclipse, and Visual Studio. Even github! Why do you have to register a new syntax highlighter on github for a language and hope they turn it on?
[+] [-] bodski|12 years ago|reply
http://bsumm.net/2012/08/11/steve-yegge-and-grok.html
http://www.youtube.com/watch?v=KTJs-0EInW8
HN discussion: https://news.ycombinator.com/item?id=4371267
[+] [-] williamcotton|12 years ago|reply
Well maybe if we stopped using ASCII files as our source code and used a richer type of document we could start to make some improvements!
What kind of rich document? Well, what about HTML? Did you know you can even embed interactive elements in such documents? What if we started embedding our source code and editors in our documents instead of the other way around? The whole model is inverted, but mainly for historical reasons, because you know, in 1979 all we had was VT100 to interface with our machines... it's like we never moved on... why is my "code" a splattering of ASCII files in a directory? A package definition, tests, dotfiles for this and for that... ship the editor, the tests, the docs, the examples, and the source ALL as one document!
[+] [-] orangeduck|12 years ago|reply
I'm also a big fan of DSLs and would love see some of the things you mention. My next (fun) big project is actually not so far from the same lines ;)
Many thanks to everyone for the kind comments! It really is encouraging. :)
[+] [-] jacquesm|12 years ago|reply
I spent the better part of the last two years writing a (closed source, sorry) library that does some of this, and some other stuff besides (state machines, events, 'proper' strings with automatic garbage collection and allocation, message passing).
Maintaining static typing was a big pre-requisite for that library, without it too much of value would be lost to offset the gains. It was a very educational project for me, it definitely re-inforced the 'half of common lisp' meme.
To program a piece of software using that library no longer felt like programming in C, every now and then you'd see a bit of C shine through in the lower level code. The whole thing relied to a ridiculous degree on macro cleverness (something to be avoided, for sure) and other deep knowledge of how C works under the hood to get certain effects, and I found this part of it less than elegant (even if the results were quite a big step up from programming in C).
The main justification for doing all this was to straighten out a project that had become bogged down under increasing complexity and a failure to abstract out the common elements. Choosing C for this project was a poor decision but since there was not going to be any budging on that front I tried to make the job work out as good as possible.
It's quite interesting to see how far you can push C but at the same time you really have to ask yourself if you are on the right road if you find yourself doing things in such a manner.
Like Cello, the lib I wrote is a way to force the language to become another language, which always has drawbacks in terms of unintended side effects and long term support.
Probably better to switch to a platform that is closer to your problem domain (in this case, such as erlang, clojure or even go), as much as I liked tinkering with C it felt like we were making life harder than it needed to be.
[+] [-] makmanalp|12 years ago|reply
I'm looking for standards / set of libraries / best practices for "modern" C development, but I've yet to find a comprehensive resource.
Stuff like typedefing a manual fixed sized int type to be cross-platform compatible, that books don't really tell you to do but are important and come up often.
I'd be okay with a small, well written example library too. Does anyone happen to know something like this?
edit: Ah, sorry if I misled you, that was just an example of the kind of tips and pointers I was looking for. Or weird bits like the linux kernel list_head. http://kernelnewbies.org/FAQ/LinkedLists Or common libraries like bstring that make life easy. Or even a single, comprehensive implementation of good data structures, since everyone seems to have their own vector.h and/or hash.h that fails to cover much other than their own use case.
[+] [-] kqr2|12 years ago|reply
http://www.amazon.com/Interfaces-Implementations-Techniques-...
It uses Donald Knuth's literate programming which takes getting used to, however, it's a great case study of how to make a good library.
There is a new book on "21st Century C" which I haven't read. It has mixed reviews, however.
http://www.amazon.com/21st-Century-Tips-New-School/dp/144932...
[+] [-] mtdewcmu|12 years ago|reply
The fixed-size int finally got a permanent solution: #include <stdint.h>
If you are targeting autoconf/automake as your build system, that has a lot of built-in solutions to portability issues, like defining macros. It's not easy to learn, and I don't pretend to know it well, but when I'm compiling someone else's project, I'm always happy to see a configure script.
The gtk project's libglib is a pretty comprehensive library of C data structures. The Apache Portable Runtime serves a similar purpose: http://en.wikipedia.org/wiki/Apache_Portable_Runtime
What I find annoying about libraries like glib is that they tend to impose their own style on your project by using their own typedef'ed types and such.
If you don't mind it, you can cobble together your own data structures from various open-source projects. Judy arrays are pretty fast, and you can use them in a variety of ways. Searching google for "c hash table" came up with a lot of excellent results, so try googling whatever data structure or algorithm you need, and chances are, you'll find something.
[+] [-] bjourne|12 years ago|reply
Then you have https://wiki.gnome.org/Vala which is a whole new language built on top of C + Glib/Object whose main selling point is that it compiles to, and is totally compatible with, plain C code.
Do keep in mind that all of this, Glib, Vala, Cello and other "make C more like a high-level language" are basically hacks to workaround the fact that C is a very low-level language and lacks many powerful features. I believe one is much more productive using Glib + C than just plain C, but you are still less productive than if you had choosen a modern language in the first place.
[+] [-] ldite|12 years ago|reply
If you're lucky enough to be able to rely on C99: https://en.wikipedia.org/wiki/Stdint.h#Fixed-width_integer_t...
[+] [-] VMG|12 years ago|reply
[+] [-] unknown|12 years ago|reply
[deleted]
[+] [-] JoachimSchipper|12 years ago|reply
[+] [-] mjn|12 years ago|reply
[+] [-] hugs|12 years ago|reply
$ gcc -lCello -std=c99 -fnested-functions example.c -o example
Hope this helps someone!
[+] [-] breckinloggins|12 years ago|reply
[+] [-] eblume|12 years ago|reply
I personally have no problem with it (other than the syntax needed to unbox/rebox values). I find that having the freedom to use a type system or not a very compelling feature in a language.
That being said, I understand why it might sit very poorly with some.
[+] [-] optymizer|12 years ago|reply
[+] [-] dcope|12 years ago|reply
[+] [-] diaz|12 years ago|reply
Gonna read some more when I have time, I could learn something from this.
[+] [-] McUsr|12 years ago|reply
I love the idea!
Hopefully, I can manage to make it work with CoreFoundation in OS X.
Maybe I'll end up with CoreFoundation+ :)
[+] [-] kragen|12 years ago|reply
[+] [-] ExpiredLink|12 years ago|reply
Side note: this book would certainly be down-voted on r/programming but I expect more grown-ups here.
[+] [-] da02|12 years ago|reply
[+] [-] ExpiredLink|12 years ago|reply
http://www.amazon.com/dp/1556155514
[+] [-] JonFish85|12 years ago|reply
[+] [-] yk|12 years ago|reply
But I think there could be quite interesting uses for Cello, namely you do your prototyping with it and then you trow out the library and refactor the code to pure C.
[+] [-] robododo|12 years ago|reply
[+] [-] JoachimSchipper|12 years ago|reply
In the same vein, but more C-like: http://p99.gforge.inria.fr/p99-html/.
[+] [-] ambrop7|12 years ago|reply
[+] [-] mcpherrinm|12 years ago|reply
[+] [-] koenigdavidmj|12 years ago|reply
[+] [-] Demiurge|12 years ago|reply
[+] [-] tehwalrus|12 years ago|reply
[+] [-] maaku|12 years ago|reply
[+] [-] georgeg|12 years ago|reply
[+] [-] Demiurge|12 years ago|reply
[+] [-] popee|12 years ago|reply
1. sizeof(function) -> would give user ability to copy functions around.
2. maybe new reserved keyword _Func -> function tagged with _Func would indicate that function must be compiled as function object (defined sizeof) and compiler needs to address fact that function may be moved around and used (relative addressing and i guess bunch or others problems that would arise). Only code, nothing to do with ELF or other formats.
Another interesting thing to do would be to, somehow, eliminate function pointers with _Func.
In any case, user would be responsible for creating environment for that (lambda?) functions, like manually setting mprotect or setting up stack (prologue.h & epilogue.h ???).
_Func int example_prototype(int i, int j) {
}And then do something like:
example_prototype func0;
memcpy(&func0, example_prototype, sizeof(example_prototype));
struct prologue_t *p_ptr = &func0;
p_ptr->sp = 0xdeedbeef; // Or some address that is used as stack
z = func0(5, 6)
So, what do you thing how hard would it be to implement something like that?
[+] [-] groue|12 years ago|reply
[+] [-] sovande|12 years ago|reply
[+] [-] al3xbio|12 years ago|reply
[+] [-] eonil|12 years ago|reply
[+] [-] Demiurge|12 years ago|reply
[+] [-] sspiff|12 years ago|reply
[+] [-] jnbiche|12 years ago|reply
[+] [-] jnbiche|12 years ago|reply
[+] [-] dubcanada|12 years ago|reply
[+] [-] 0x09|12 years ago|reply
[+] [-] egonschiele|12 years ago|reply