Shop OBEX P1 Docs P2 Docs Learn Events
Lost in C? - Page 2 — Parallax Forums

Lost in C?

2»

Comments

  • D.PD.P Posts: 790
    edited 2012-12-22 10:50
    4x5n wrote: »
    I don't :-)

    Don't get me wrong I have nothing against forth but it's just not a language for me. For what it's worth neither are cobol or python (nothing against cobol or python either). I have to admit I'm getting tired of the bickering about <insert programming language of your choice> VS <a language you don't care for>.

    Can we please stop the language proselytizing. Use whatever language that you like!!

    Agreed, let's all just focus on helping each other no matter what language they choose.
  • rod1963rod1963 Posts: 752
    edited 2012-12-22 11:26
    Peter

    Hardly sweeping, companies like Freescale have been making 16bit microcontrollers for over 15 years that deal with signals processing, filtering etc. Now on low end systems that you work on it's a different story.

    But it's clear Forth was oversold by it's adherents, when I did Forth programing 20+ years ago, the Forthers were always bragging what a great RAD tool Forth was. But they could never back it up, Forth just came out looking real bad. Then there is the interactivity claim. Interpretive BASIC running on the bare metal could do the same thing.
  • potatoheadpotatohead Posts: 10,261
    edited 2012-12-22 11:31
    I just had to comment on "assembly vibe" and expressions noted by Heater.

    Yes, precisely.

    I've always had a little trouble with expressions. The norm today is "infix", and do I have that right? [ x*(y+3)-4] kind of thing... I get those and can translate them to assembly language fairly easily, using the parenthesis to dictate flow, in the assembly language case. And I can do the same with many higher level languages I know, even when I don't know too much about that particular language.

    With Forth, I find the stack operators obtuse and I know absolutely that is me not doing the work to pound them home, and I'll riff on that shortly, just hold the thought. IMHO an expression evaluator word in Forth would help newcomers considerably.

    So, let's say I do that pounding home and can easily write expressions in Forth. The obtuse nature of it means I must also either commit a lot of meta-data to memory, or provide supporting documentation because the Forth code produced isn't anywhere near as self-documenting as a well named standard expression is. A similar example of the problem can be found in UNIX regular expressions, so it's not just Forth that exhibits "write only" type behavior. For me personally, this is not optimal, simply due to the fact that I'm not committing to the language and that makes it kind of thick for me..... And thick just doesn't work well because the entry and exit costs are too high.

    Then comes the other matter. Forth is like assembly language in that the core of Forth is small, powerful and portable, in that boot strapping a kernel onto something is a pretty darn lean activity. I really like that about Forth BTW. IMHO, one of it's strongest suits.

    But then comes the variations... Just like assembly language, people are completely free to invoke whatever structure makes sense, and with things like macro assemblers, can build really big stuff, but reuse potential is kind of low, depending, and CPU variances are not reusable very much at all.

    I find the various Forth variants to be very analogous to CPU variants in assembly language exhibiting many of the same difficulties. If I see some killer 6502 routine I like, and I want to do it on a Prop and a 6809, I know all three of those well enough to port the routine and re-use it. Say that same routine came from a Z80? Well now I'm in trouble, because I've got to go back to the core instruction docs and parse that CPU, map that to what I do know, then build up, test, etc... That is what moving from one Forth variant to another one is like, and where the unique "instructions" or words aren't really documented well, I've got to start at the kernel, parse that, then up through the dictionary and eventually to that magic word and grok it! Possible to do, but not realistic for me as anything other than a fun exercise.

    Please don't take this as a Forth sucks post. It's not. I had a good time with my old Apple Forth, Tachyon, and ANSI Forth on the PC tinkering about making small things happen. On that level, I get it and can knock out some little routine or other fairly efficiently, so long as there aren't significant expressions in it, then I have to pause and either draw a stack diagram, or understand how globals are made, then build from there...

    I find the advocates of Forth to be very similar to advocates for assembly language in many respects. And here's the key thing: Where any of us does make a significant investment in either one, we get something that we can build on, and it's fast, and it rocks hard in lots of ways, but only when that investment is made, and making it kind of brands our Forth or assembly language core unique, and for others to jump on that requires they understand both the core instructions, whatever cool words were built up from that, and something about how the other person thinks before any real productive stuff falls out of that.

    IMHO, that's the difficulty in a nut shell, as least for me. Put another way, it's like learning German to understand how to assemble my new toy, and then French to assemble the other one, combining both with my own spudlingish to employ both and proceed to the task at hand. A lot like that, or maybe just find both toys in French, or author the missing one in French to avoid German to get to the task. This is due to the language of Forth being designed to create languages to get stuff done as opposed to other languages that are designed to render many different things to get stuff done in a standard way. Some people have great linguistic skill, others don't, and I don't think I do, which makes Forth really hard.

    Because Forth hides so much and is so very basic at the core, learning just that doesn't yield too much. One is left on a little island, unable to get out without building or parsing an awful lot of stuff. Primary barrier to entry, IMHO.

    Now, with assembly language, there is a difference! In many cases, the core basics can be learned and applied in a compartmentalized and specific way, which then can be incorporated into a simpler, or higher level construct! With a BASIC, C, SPIN, you name it, there is a fairly large body of code that gets you out to the real world, meaning you can jump in, tap the benefit, then leverage that higher level environment with a lot of reuse, even when it's something like BASIC, which isn't too reusable directly.

    With Forth, it's not really higher level until somebody has done the building to make it so, thereby creating a dialect that can and basically does vary from other works of the same type. I find I can use Tachyon lightly, for example, once I understand what Peter built. And it's fast, and all that other good stuff too, but that's kind of it. Should I move on and out to something else, I'm kind of stuck. On the other hand, when I use a more general Forth, more of what I work on works in more places, but it's not fast, etc...

    So there you go. That was my experience. Enjoyed it and Forth did make me think a bit differently, and I really do appreciate the basic nature of it too. A skilled Forth programmer can boot strap themselves onto just about anything quickly, and if that's in high demand, I consider Forth very worth learning. Additionally, if the target application scope is somewhat closed, like the UPS reader devices often cited, or the NASA stuff that uses Forth, I also consider it very worth learning because once that building is done, that environment is going to rock hard, be robust and all that other good stuff.

    However, if one is seeking more general purpose interaction, reuse and code sharing, etc... like we do here, Forth is difficult because it requires one to invest a considerable amount of meta learning before it really becomes clear enough to be useful "copy paste run" style like PASM, SPIN, C, BASIC is.

    Again, those were my experiences and I'm just putting them here to riff on what Heater said because it resonated a little with me and I find the discussion interesting, that's all. Honestly, I admire the skill and investment shown by some of the Forthers here. Bad a$$ good, embedded stuff. Hats off to you guys sharing it, and maybe you will get a new peer or two out of the whole thing, which is good for that peer and the group of Forthers overall.

    If I had some serious incentive to go that way, I see the appeal, and I know what I would need to do now in order to get there. Maybe someday when that opportunity presents itself, I'll be in a position to have it pay off, and you guys have shown me what that looks like too. Thanks!
  • potatoheadpotatohead Posts: 10,261
    edited 2012-12-22 11:47
    BTW: The reason why Forth has that perception of being "still in the 70's" is due to the fact that the language definition is minimal along with syntax by design. One builds a language to get the task done in Forth. It's the dialects that result from this that keep it from spreading. If we were to take the Forth environment built up to realize the UPS readers and attempt to repurpose it, we would find some root words of the dialect useful, and if we understand the very core of Forth, we can parse that environment from the kernel up to understand what all the words in it mean, then we would design a new dialect to realize whatever the task to be accomplished is. This would result in two dialects, both sharing some basic stuff, but both very unique too. Understanding this requires a lot of head space! Difficult for many people, IMHO.

    The same thing done in C, for example, doesn't require a full on understanding to be repurposed! Most languages are defined fully, with the task being expressed in those full terms, requiring one only understand enough of the language definition to understand the logic behind the task. And that understanding is broadly applicable because it then applies to all tasks authored in that particular language. You can present a C programmer some body of code, they can glance over it and say, "Hey, let's take this math routine and go!" useful stuff. Unless that routine is written very poorly, it's usable and can be parsed as is, even stand alone, much of the context missing.

    The same thing in Forth might not be true, unless it was written with the very core words, and even those can, do, will, should vary depending on what the Forth kernel does for it's hardware platform.

    Another way to express the difference I guess, as I see it anyway.
  • Heater.Heater. Posts: 21,230
    edited 2012-12-22 12:47
    ...your entire problem is that your inability to program in C when using forth
    Perhaps, but unlikely. I don't have a problem not programming in C when I program in Pascal, Python, JavaScript, Go, Spin, PASM. All of which I have been doing this year. I had no problem not programming in C when programming in PL/M, Coral 66, ALGOL, Ada, BASIC, XC, Occam etc ect etc in former lives.

    As I have mentioned before, many of these languages look sperficially similar syntax wise. C and Java Script for example. But their semantics are vastly different and demand different programming styles.

    Why should Forth be any different? There is no deep magic in Forth.
    You have not gotten your head around the different of between C local and global variables versus forth stack location versus memory locations.
    Sure I have.

    C has global and local variables. Forth does not have any variables, global or otherwise. Or at least none that I can find.

    What it does have is the possibility to name things. Names can be used to represent "words" ("functions" as we might call them in other languages). Names can be used to represent addresses of memory locations.

    In Forth when I use (as opposed to define) "Aname" that is either going to execute a word of that name or it's going to fetch an address an place it on the stack.

    Do correct me if I am wrong.

    Forth of course has data local to a word. That's the stuff sitting on the stack. Parameters passed in or just things being worked on locally. I hesitate to call that "local variables" because those stack items have no name and no type nor any other feature normally implied by the term "variable" in a language.

    Problem is that data on the stack is hard to get at add. dup, swap, over and so on.
    Nor have you gotten you head around doing simple functions and building them into complex functions in forth,
    Perhaps. Generally I'm into a top down approach. You have to know what you want and draw up an outline. The details can wait. Of course while doing that you have to have some confidence that you have the means of filling in those details.

    My chosen problem is already a very simple function, it's kind of atomic and self contained. Only 12 lines of pseudo code:
    X0,...,N&#8722;1 &#8592; ditfft2(x, N, s):             DFT of (x0, xs, x2s, ...,
    x(N-1)s):
        if N = 1 then
            X0 &#8592; x0                                      trivial size-1 DFT base
    case
        else
            X0,...,N/2&#8722;1 &#8592; ditfft2(x, N/2, 2s)             DFT of (x0, x2s, x4s, ...)
            XN/2,...,N&#8722;1 &#8592; ditfft2(x+s, N/2, 2s)           DFT of (xs, xs+2s, xs+4s, ...)
            for k = 0 to N/2&#8722;1                           combine DFTs of two halves into full DFT:
                t &#8592; Xk
                Xk &#8592; t + exp(&#8722;2&#960;i k/N) Xk+N/2
                Xk+N/2 &#8592; t &#8722; exp(&#8722;2&#960;i k/N) Xk+N/2
            endfor
        endif
    
    So there is "the plan". Of course it hides a lot of details like the fact that we are using complex numbers, or how to do "exp"

    Aside: As this is just an exercise, it does not matter that this is actually an FFT, it could be anything.

    So yes, you are correct. Having got the plan I need to be able to chop that down into manageable chunks and implement them.

    But, that means we need to know how we are going to represent this data, e.g. complex numbers, and arrays of complex numbers. And we need to know how we are going to pass those parameters to ditfft2, on the stack, as globals, some other way? You can't build the little chunks until you know what they are supposed to do and how they will be used.

    If anyone can supply a nice example of a complex multiplication in Forth I would be very grateful and perhaps get a sense of how Forthers get things done.
  • potatoheadpotatohead Posts: 10,261
    edited 2012-12-22 13:02
    Heater:

    See: https://groups.google.com/forum/?fromgroups=#!topic/comp.lang.forth/AMKW_8-2j_s

    And in particular, this lexicon:

    http://www-personal.umich.edu/~williams/archive/forth/complex/complex-kahan.fs

    Quite literally, Forth has nothing defined. You would ALLOT a scratch area, then extend the language to employ it in ways that make expressing your multiplication sane, then perform said multiplication. Wash, rinse, repeat layer by layer until you get to [data] FFT emit.

    Note:

    That lexicon depends on others...


    ANS Forth environmental dependences: 1. Requires the Floating-Point and Floating-Point extension word sets. 2. Assumes a separate floating point stack. 3. Does not construct a separate complex number stack. 4. Case insensitivity for standard words. 5. The ANS FORTH default floats must be 32-bit or 64-bit IEEE 754 to work correctly with signed zero/infinity. 6. Some of the Kahan algorithms are optimized for radix 2. 7. Machine parameters like EPSILON and a few others have to be uncommented, or supplied if they are not 32-bit or 64-bit IEEE 754. The parameter section assumes that raw floats are represented in memory as contiguous sets of bytes that are totally big-endian or little-endian, with the raw representation of -1E nonzero in the logical first byte and zero in the logical last byte. 8. If not present in the host FORTH, FSIGNBIT assumes default floats to be IEEE 754 32 or 64 bits, and also assumes the cell size to be a multiple 32 bits. 9. There is a system dependence on the sign of NaN produced by an arithmetic operation. In particular, Z^ currently gives NaN's with plus signs on ppc and minus signs on intel systems, for both 0+i0^0+i0 and 0+i0^1+i0, with both pfe and gforth. So does F/ for 0/0. Complex numbers z=x+iy are stored on the fp stack as [f: x y], also written as [f: z].

    So then, we move to the ANSI Forth floating point extensions:

    Look at this:

    ANSI X3.215-1994 : FLN 1.0E0 F- FLNP1 ; See: A.12.6.2.1516 FEXPM1. A.12.6.2.1616 FSINCOS See: A.12.6.2.1489 FATAN2. A.12.6.2.1640 F~ This provides the three types of "floating point equality" in common use -- "close" in absolute terms, exact equality as represented, and "relatively close". A.13 The optional Locals word set The Technical Committee has had a problem with locals. It has been argued forcefully that ANS Forth should say nothing about locals since: - there is no clear accepted practice in this area; - not all Forth programmers use them or even know what they are; and - few implementations use the same syntax, let alone the same broad usage rules and general approaches. It has also been argued, it would seem equally forcefully, that the lack of any standard approach to locals is precisely the reason for this lack of accepted practice since locals are at best non-trivial to implement in a portable and useful way. It has been further argued that users who have elected to become dependent on locals tend to be locked into a single vendor and have little motivation to join the group that it is hoped will "broadly accept" ANS Forth unless the Standard addresses their problems. Since the Technical Committee has been unable to reach a strong consensus on either leaving locals out or on adopting any particular vendor's syntax, it has sought some way to deal with an issue that it has been unable to simply dismiss. Realizing that no single mechanism or syntax can simultaneously meet the desires expressed in all the locals proposals that have been received, it has simplified the problem statement to be to define a locals mechanism that: - is independent of any particular syntax; - is user extensible; - enables use of arbitrary identifiers, local in scope to a single definition; - supports the fundamental cell size data types of Forth; and - works consistently, especially with respect to re-entrancy and recursion. This appears to the Technical Committee to be what most of those who actively use locals are trying to achieve with them, and it is at present the consensus of the Technical Committee that if ANS Forth has anything to say on the subject this is an acceptable thing for it to say. This approach, defining (LOCAL), is proposed as one that can be used with a small amount of user coding to implement some, but not all, of the locals schemes in use. The following coding examples illustrate how it can be used to implement two syntaxes.

    Found here: http://www.forth.org/svfig/Win32Forth/DPANS94.txt

    And I found this!

    http://www.figuk.plus.com/codeindex/all_by_author.html

    Down the rabbit hole all different directions.

    What I see then is a set of choices:

    1. Decide how you want to represent floats and define those words to operate in space you ALLOT for that purpose, and you do that with the words you have now and whatever scheme is provided to ask for memory and deal with addresses, then build up from there to realize the floating point core you need to express your routine. Do this in terms of the kernel you are running on, meaning you do it first, then optimize those words for speed by extending the kernel as needed once the vision is seen as viable, or....

    2. Extend the Forth you are running on such that it meets the dependencies of the routines that are out there, then simply bring that lexicon in, using those words to express your routine.

    3. Write it in PASM, package that up and invoke it with a word, using core Forth to simply pass values around and manage logic, etc...
  • prof_brainoprof_braino Posts: 4,313
    edited 2012-12-22 13:10
    Heater. wrote: »
    Perhaps, but unlikely. ... Pascal, Python, JavaScript, Go, Spin, PASM. .... PL/M, Coral 66, ALGOL, Ada, BASIC, XC, Occam etc ...

    C has global and local variables. Forth does not have any variables, global or otherwise. Or at least none that I can find.

    Well, there's the first part of your problem.

    VARIABLE assigns a name to a storage location. Full stop. All similarities to other uses of the term variable as used in other languages end there. We can either accept that and use it to an advantage, or complain about it.

    In summary, if you want to assess a value quickly, you want the top of the stack. If you want something that you can't have waiting at the top of the stack, get it from a memory location (and thus put it at the top of the stack). Getting a value from a memory location to the top of the stack has more steps so takes more time. This seems to be where you are having your issues.

    But that's off topic. This thread is about how loopy likes to use forth because of the interactivity, and can apply his experiences to other development. Other folks opinions may vary. Geez! Try to relax, and enjoy life. The world is going to end tomorrow. Or was that yesterday?
  • prof_brainoprof_braino Posts: 4,313
    edited 2012-12-22 13:35
    Dave Hein wrote: »
    Doug, you make a LOT of comments about how people are approaching Forth programming in the wrong way. Have you ever thought that the problem is with Forth and not the programmer? .

    Yes, I have thought about this, and No, the problem does not lie with the tool. If one complain that assembler is too obtuse, is the problem with assembler or with the complainer? I think these are the same question.

    If using the clutch is too hard, then one should drive automatic and not ask to use my car. But you can go ahead and try forth, at least you won't run over a kid or crash into a tree.
  • Heater.Heater. Posts: 21,230
    edited 2012-12-22 13:51
    Braino,
    VARIABLE assigns a name to a storage location
    No, it does not. VARIABLE assigns a name to the address of a storage location. In Forth you cannot have a name for a variable only the address of a variable. The Forth word "VARIABLE" is a misnomer.

    I can demonstrate that this is so with a session my gforth:

    First use "variable" to define a name
        variable foo  ok
    
    Let's put a value in there:
        42 foo !  ok
    
    Now let's see what that name gets us:
        foo . -1222527056  ok
    
    Clearly foo is not a variable but some address. I need some extra indirection to actually get to my variable:
        foo @ . 42  ok
    
    Hence my statement that Forth does not have variables.

    And my growing realization that many issues I am having with Forth result from the fact that Forth is not even described in the same language used in mainstream computing discussion. The meta language is different.
    We can either accept that and use it to an advantage, or complain about it
    I can accept that little detail and move on.
    ...if you want to assess a value quickly, you want the top of the stack.
    Yep, the problem then is how to get the value to the top of the stack, or arrange that the values you want are there when you want them.
    If you want something that you can't have waiting at the top of the stack, get it from a memory location
    Yep. But then I'm into using global variables. Not good. But we have already agreed that that is the best way to go for now, so that's what I'm doing.
  • potatoheadpotatohead Posts: 10,261
    edited 2012-12-22 13:54
    Am I missing something, or isn't the core problem Heater is having merely nobody actually doing complex multiplication on these Forths before?

    Until somebody does, there simply are not the definitions to do them with, right? Which leaves the choices mentioned above.
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-12-22 14:57
    Complex multiplications are just implemented as the product of 2-point vectors. Most of the operations in the FFT are reduced to "butterfly operations", which is something like the following:
    x1 = c*x0 + s*y0
    y1 = s*x0 - c*y0
    
    where s and c are the sine and cosine of a certain angle. I probably don't have the minus sign in the correct place, but the general idea is something like that. This should be fairly easy to do in Forth without global variables. It will just require a lot of silly stack twiddling, but it's doable.

    BTW, you can create variables in Forth that produce their value when referencing them by name by using the VALUE word. New values are stored using the TO word. So you could do something like this:
    0 value x0
    0 value y0
    0 value x1
    0 value y1
    0 value c
    0 value s
    c x0 * s y0 * + to x1
    s x0 * c y0 * - to y1
    
    ...
  • Heater.Heater. Posts: 21,230
    edited 2012-12-22 15:26
    Dave,

    Thank you. I kind of skipped over the VALUE thing as in whatever tutorial I was reading they were introduced as constants. Little did I know that in the Forth world constants are actually variable:)

    Anyway since I was away I made a complex mul using VARIABLE
    variable Ar    \ Real part of A
    variable Ai    \ Imaginary part of A
    
    
    variable Br    \ Real part of B
    variable Bi    \ Imaginary part of B
    
    
    variable Rr    \ Real Part of result
    variable Ri    \ Imaginary part of result
    
    \ t1 = Ar(Br + Bi) 
    \ t2 = Bi(Ar + Ai) 
    \ t3 = Br(Ai - Ar)
    \ Rr = t1 - t2
    \ Ri = t1 + t3
    \ Complex multiply using only three multiplications.
    : complexMul 
        Br @ Bi @ + Ar @ *     ( t1 )
        Ar @ Ai @ + Bi @ *     ( t1 t2 )
        2dup - Rr !            ( t1 t2)
        drop                   ( t1 )
        Ai @ Ar @ - Br @ *     ( t1 t3 )
        + Ri !                 ( )
    ;
    
    : test 
    
       1 Ar !
       2 Ai !
       3 Br !
       4 Bi !
       complexMul
       ." Expect -5 10"
       cr
       Rr @ .
       Ri @ .
       cr
       ;
    
    
    test
    

    Now I could use change that to use VALUE. But what I'd rather have is for complexMul to take addresses of its parameters so that I can point it at any numbers I have.
Sign In or Register to comment.