[[email protected]: Re: Arduino frustrations: C is not a higher-order language, and timing is not an optimization]
Kragen Javier Sitaker <[email protected]>
| Newsgroups | gmane.culture.people.kragen.discuss |
|---|---|
| Message-ID | <[email protected]> |
----- Forwarded message from Tomasz Rola <[email protected]> ----- Date: Tue, 3 Jan 2012 00:14:09 +0100 (CET) From: Tomasz Rola <[email protected]> To: Kragen Javier Sitaker <[email protected]> Cc: Tomasz Rola <[email protected]> Subject: Re: Arduino frustrations: C is not a higher-order language, and timing is not an optimization On Mon, 2 Jan 2012, Kragen Javier Sitaker wrote: > On Mon, Jan 02, 2012 at 05:15:03AM +0100, Tomasz Rola wrote: > > On Sun, 1 Jan 2012, Kragen Javier Sitaker wrote: > > > So the upshot is that I end up doing a lot of stuff either by hand > > > or at runtime that I'd like to do automatically at compile time, and > > > then I have to debug problems by trial and error instead of getting > > > useful error messages. > > > > Hello, > > Hi! May I post your response, and this response to it, to kragen-discuss? Sure, no problem. If you find this mail of enough value, you can also repost it. Small edits are ok to me, I trust that you will do it well. > You can probably get something running on an Arduino (using their IDE, not > Forth) with US$20 and half an hour. Try it, it'll be fun! Yes, I read some blog entries (ditto with "half an hour" in their titles). I might try Arduino one day, but frankly I like to compute on some bigger scale. Perhaps I would be ok with few kilowords of ram, but with 8-bit words... well, this fills so small... On IBM 704, they had 4-32Kwords but a word was 36-bit. One could put some data into it and I guess, 36-bit arithmetic was there in hardware. This was enough to make first LISP interpreter on it. I watch Arduinos closely, but for a moment I'm not decided. Nowadays, one can really have other options that look more sexy to me - like, FPGA + 128MB of ram, packed into USB stick or something equally small. I am unable to find the page right now, but from what I remember pricewise it was competitive to A* (especially when comparing what could be packed into them). So, I like small things but I also want them to have some usable power - something comparable to PDP-10 or similar machine would probably make me happy, especially for few tens of dollars. I am not into them right now, but I can easily wait a bit and by the time I'm ready their prices will be even more interesting, I guess. About 8-bits - I have nothing against them but, well, not really much can be done with 8-bit cpu. It can be great fun on one hand, but on the other hand once I laid my fingers on my first 16-bit computer (that was Amiga and was, actually, almost 32-bit - muls and divs were 16bits AFAIR) I have never looked back. Ditto for 32-bits. And now I am slowly migrating to 64. All my enthusiasm for 8-bit flattens when I recall that maybe I would be able to make character terminal with it, but would have to connect to someting bigger if I wanted to do anything useful for my current activities... I guess I am more like software guy, hardware is good if I can push it as hard as I want. BTW, Arduinos might find themselves on a warming up ice. From the upper side, there are coming all kind of 32-bit ARM boards and FPGAs. From the lower side, there are plenty of cheaper 8-bit cpus, like Atmels or even 8051. So far, Arduinos win because they are easy to begin with and to tinker later - but this comes at some price. So even if I choosed them, I would want to switch one way or another, a bit later. > > but if there is a chance you never heard of Forth, here is my chance to be > > helpful. Yes it looks strange. And I tried it a bit and it is quite good > > thing for a strange language. > > In some ways it could help. For example, building a data structure to > represent a video frame type at compile time, then compiling that into a > machine-code routine to generate the video frame, could be done easily in > Forth. > > But in others, it's kind of the opposite direction. A big part of my > complaint is that I want the computer to detect bugs (e.g. your stack is > going to overwrite your heap) for me. With C, the compiler detects if I > pass the wrong number of arguments to a function, or if I have a type > error, but not if I have unbounded stack depth or if my execution time > is nondeterministic. With Forth, the compiler won't even detect if I > pass the wrong number of arguments or try to dereference an integer. > Forth's terseness makes it Actually, I think you can't pass it wrong number of arguments - either there is enough values on stack, in which case it will work, even erratically, or there is not enough, in which case I believe it will stop with error. > <http://www.yosefk.com/blog/my-history-with-forth-stack-machines.html>, > after ending up with 700 lines of code like `dup um* nip FRAC 2 * 32 - > rshift -rot`. In the comments, Samuel Falvo calls this "*the* classic > beginners Forth problem -- way way WAY too many items on the data > stack." This is very interesting article, and it even tought me few new things about Forth :-) . However, I think he fell into a trap of very different kind than you mention. Simply, Forth is not for everyone. To use it requires sometimes even rephrasing a problem, to an equivalent form that matches Forth capabilities. He was a guy in a middle of a bigger firm, had to use his people and Forth could not fit there as a programming language. I understand that they were happy with their forth-like cpu, however. With another team and people using Forth on a daily basis for a longer time, the story might have ended differently. But this could require, for example, totally different hardware from the one described in a story. > It turns out that Forth has not only the stack, but also access to > memory, plus another stack; and the right way to do things, in my view, > is to use VARIABLEs in Forth in almost all of the same cases where you > would use variables in C. This might sound like a terrible idea, because > Forth VARIABLEs are global, while C has local variables. And we all > know global variables are evil. It is always the same story, global vars are evil, gotos are evil and so on, but once we learn to not use them, we also learn to use them from time to time because they might do the job in some cases. BTW, alternative to global vars is functional programming and until recently, I think, gcc wasn't up to the task. Things like deep recursion depend on tail call optimisation (in short, rather than allocate million stack frames to compute 1000000! you only allocate one and reuse). Global vars are still used but are read only, i.e. constants. Everything a function needs is passed as arguments or constants. But, I remember you mentioned about having only 2KB or ram. In such case, all rules are out of the window. You can try functional-style in C, maybe it will fit into your ram but I'm afraid you will not like it. > Here are some of the problems global variables cause in C and related > languages: > > 1. They live in a single global namespace, so if you try to define two > variables with the same name, you get link errors. Or you get a > single variable, being used by two different pieces of code that > shouldn't be interacting at all, causing bugs in them. And it's hard > to find all the references to the variable, because they could be > anywhere in the program. > 2. It's possible to have an execution path that fails to initialize > them, leaving values from a previous execution, leading to subtle > bugs. In effect, they give persistent state to a part of the system > that doesn't need it, and stateless code is always more reliable and > easier to test. > 3. In a recursive call, every activation record of a subroutine has its > own instance of its local variables. Recursion is still a somewhat > tricky construct --- you have termination concerns that don't arise > with nonrecursive calls, plus potentially unbounded stack usage > potentially causing data corruption (on the Arduino and similar > environments) or a program crash --- but it's less tricky when each > call has its own local variables. > 4. Multithreaded access to global variables requires synchronization > between the threads, or you get subtle race-condition bugs. Yes. Those problems, without thinking on them too deeply, all seem to stem from the tiny architecture. With 1MB of ram, proper mem mgmt routines and compiler that knows how to generate code, they would probably be gone. As I wrote, with 2KB of ram, all rules are out and even C is incredibly high level IMHO, only it really is not and there is not enough place to help it. I would give Forth a try anyway, even though you are right that code from yosefk's blog was quite cryptic at first sight. As the guy himself wrote, all of this was result of pushing wrong thing into box not designed to hold it (at least this was how I read it). OTOH, I don't think one can use Arduino for anything very complicated (I mean, algorithmically). Since you don't like assembly and C has problems, something from between may be the best bet (the funny thing here is that with this middle-ground tool one can probably do more than with other choices). Even if Forth code is hard to read (maybe it's not, maybe one just needs some practice to write) - I think you'll stay below level of complexity that makes reading impossible. Most probably you will know your code by heart. But of course it's a bit hard to be sure without knowing what you try to do - my only hint being maximal code size possible to fit into your hardware. Google told me that amforth works on A*s, and there was 50-min video about it on youtube (which I didn't have time to watch). Regards, Tomasz Rola -- ** A C programmer asked whether computer had Buddha's nature. ** ** As the answer, master did "rm -rif" on the programmer's home ** ** directory. And then the C programmer became enlightened... ** ** ** ** Tomasz Rola mailto:[email protected] ** ----- End forwarded message ----- -- To unsubscribe: http://lists.canonical.org/mailman/listinfo/kragen-discuss