Foregone exercises

I’ve been adding some exercises lately. When I do that on a track, I often go over the exercises to see which ones don’t make sense for the track, and then add those to the foregone key. I’d like us to determine which exercises should be foregone for the 8th track.

You can find the unimplemented exercises by going to 8th impact and status on Exercism

Some candidates:

  • PaasIO: very Go-specific
  • Hangman: requires reactive programming

Then there’s data structure like exercises like 'linked-list, circular-buffer, custom-setandcomplex-number. We could setup the words such that we don't force an implementation in most of these examples, and for binary-search-tree` we could just use a map.

Then there’s struct/class/record based exercises, like robot-simulator, dnd-character and more.

CC @axtens @glennj

2 Likes

I’ve always thought it would be cool to implement the forth exercise in 8th, but I have no idea how to do it in an interesting way (that’s not just a thin wrapper around 8th builtins)

I am curious about 8th objects but I have not taken the time to dig into it. two-bucket is my go-to object-based exercise.

I don’t know how 8th is used in the wild. I haven’t seen any kind of 3rd party library ecosystem. Ron’s effort to inspire one didn’t gain any traction. So I don’t know how many exercises are wanted to practice with the builtin data structures.

Tangentially, I’ve always found the words list page quite frustrating to use, with its lack of a table of contents. I just tried the PDF version, and it’s just what I wanted:

Hah, I feel the same way, which is why I opened an issue on the forum: Improved searching on words list page

That sounds like it would be something worth checking out.

I’m thinking of doing forth for 8th. I recently did forth for euphoria and am in the middle of doing for harbour. For 8th I expect I’ll build the dictionary as a map in a manner similar to what I did for euphoria. For harbour I’m building a dbf file.

1 Like

As for documentation for 8th, I don’t find the html or the pdf particularly helpful. I’ve got plans for an EPUB version so that I can use my Kobo to view the documentation

1 Like

First draft of 8th forth (the non-brute-force version is at the bottom)

"empty stack" constant ERROR_EMPTY_STACK
"only one value on the stack" constant ERROR_ONLY_ONE_VALUE
"divide by zero" constant ERROR_DIVIDE_BY_ZERO
"undefined operation" constant ERROR_UNDEFINED_OPERATION
"unknown word" constant ERROR_UNKNOWN_WORD

a:new var, COMPILER
a:new var, STACK
true var, IMMEDIATE

: immediate! IMMEDIATE true ! ;
: compiling! IMMEDIATE false ! ;
: compiling? IMMEDIATE @ not ;

: stack.push \ n --
    STACK @ swap a:push drop 
;

: stack.swap \ --
    STACK @ a:len dup
    2 n:< if ERROR_ONLY_ONE_VALUE throw ;then
    1 n:< if ERROR_EMPTY_STACK throw ;then
    dup a:pop swap a:pop nip -rot a:push swap a:push drop
;

: stack.over \ --
    STACK @ a:len dup dup
    2 n:< if ERROR_ONLY_ONE_VALUE throw ;then
    1 n:< if ERROR_EMPTY_STACK throw ;then
    n:1- n:1- a:@ a:push drop
 ;

: stack.drop \ --
    STACK @ a:len
    1 n:< if ERROR_EMPTY_STACK throw ;then
    a:pop 2drop 
;

: stack.dup \ --
    STACK @ a:len dup 
    1 n:< if ERROR_EMPTY_STACK throw ;then
    n:1- a:@ a:push drop
;

: stack.add \ --
    STACK @ a:len dup
    2 n:< if ERROR_ONLY_ONE_VALUE throw ;then
    1 n:< if ERROR_EMPTY_STACK throw ;then
    dup a:pop swap a:pop nip n:+ a:push drop
;

: stack.substract \ --
    STACK @ a:len dup
    2 n:< if ERROR_ONLY_ONE_VALUE throw ;then
    1 n:< if ERROR_EMPTY_STACK throw ;then
    dup a:pop swap a:pop nip n:- a:push drop
;

: stack.multiply \ --
    STACK @ a:len dup
    2 n:< if ERROR_ONLY_ONE_VALUE throw ;then
    1 n:< if ERROR_EMPTY_STACK throw ;then
    dup a:pop swap a:pop nip n:* a:push drop
;

: stack.idivide \ --
    STACK @ a:len dup
    2 n:< if ERROR_ONLY_ONE_VALUE throw ;then
    1 n:< if ERROR_EMPTY_STACK throw ;then
    dup a:pop swap a:pop nip n:/mod nip a:push drop
;

{
    "DUP" : ' stack.dup ,
    "OVER" : ' stack.over ,
    "DROP" : ' stack.drop ,
    "SWAP" : ' stack.swap ,
    "+" : ' stack.add ,
    "-" : ' stack.substract ,
    "*" : ' stack.multiply ,
    "/" : ' stack.idivide 
} var, DICTIONARY

: store-compiler-code 
    COMPILER @ a:len 1 n:>
    if 
        \ [0] is name, [1..] is instructions
        a:shift >r " " a:join  
        DICTIONARY @ r> rot m:! drop
        COMPILER @ a:clear
    else
        drop
    then
;

: colon? dup ":" s:= ; 

: semicolon? dup ";" s:= ; 

: in-dictionary? dup DICTIONARY @ swap m:exists? nip ; 

: entry-is-word? dup DICTIONARY @ swap m:_@ word? ;

: parser \ s --
    s:uc
    colon? 
    if 
        compiling! drop
    ;then

    semicolon?
    if 
        store-compiler-code
        immediate! drop
    ;then

    compiling?
    if 
        COMPILER @ a:push drop
    ;then

    in-dictionary?
    if 
        entry-is-word?
        if 
            nip w:exec 
        else 
            nip " " s:/ ' parser a:each! drop
        then
    ;then 
    
    G:>n null? !if stack.push ;then 

;

: forth \ s --
    " " s:/ ' parser a:each! drop
    STACK @ a:pop nip .
;

Handles ": X dup * ; : XX X X ; 10 XX" forth properly

Non-Brute-Force version:

ns: froth

: dup G:dup ;
: over G:over ;
: swap G:swap ;
: drop G:drop ;

: + n:+ ;
: - n:- ;
: * n:* ;
: / n:/mod nip ;

: bye G:bye ;

: froth /\s+/ s:/ ( w:find w:exec ) a:each! drop ;

: frothy ns:froth only ;
: unfrothy null only ;

: .s G:.s ;

: forth frothy eval . unfrothy ;

1 Like