Given this code:
(constant 'FEN "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR")
(set 'file-list '(
("a8" "b8" "c8" "d8" "e8" "f8" "g8" "h8")
("a7" "b7" "c7" "d7" "e7" "f7" "g7" "h7")
("a6" "b6" "c6" "d6" "e6" "f6" "g6" "h6")
("a5" "b5" "c5" "d5" "e5" "f5" "g5" "h5")
("a4" "b4" "c4" "d4" "e4" "f4" "g4" "h4")
("a3" "b3" "c3" "d3" "e3" "f3" "g3" "h3")
("a2" "b2" "c2" "d2" "e2" "f2" "g2" "h2")
("a1" "b1" "c1" "d1" "e1" "f1" "g1" "h1")))
(define (fen-black? c)
(true?
(regex "[rnbqkp]" c)))
(define (fen-white? c)
(not
(fen-black? c)))
(define (fen-value c)
(if (= "_" c)
'(nil nil)
(list
(lower-case c)
(if (fen-black? c)
(string "b")
(string "w")))))
(define (fen-expand s)
(replace "([1-8])" s (dup "_" (int $0)) 0))
(define (fen-split f)
(parse
(fen-expand f) "/"))
(define (fen-list c s)
(append
(list s)
(fen-value c)))
(define (fen-parse fen)
(let (ret-list '())
(fen-parse-helper (fen-split fen) file-list)))
(define (fen-parse-helper list1 list2)
(unless (null? list1)
(let (temp-list nil)
(setq temp-list (map (fn (x y) (fen-list x y)) (explode (first list1)) (first list2)))
(until (null? temp-list) (push (pop temp-list) ret-list))
(fen-parse-helper (rest list1)(rest list2)))
(eval 'ret-list)))
I'd like to combine fen-parse and fen-parse-helper, but I was lucky to get this far! Suggestions? Comments? Criticisms?
--hsm
Hi hsm! Nice to see the code flowing from your finger-tips!
Although some of the superbrains on this forum might be able to see at a glance what you're doing, I'm struggling to see how you call your functions, with what data, and what you expect them to return. :)
It might be an idea to distil your code down to the simplest skeleton possible, to reduce the cognitive load. At first glance it doesn't look like you're calling fen-parse at all...
I call fen-parse from the repl but...
Think of fen-parse as an ignition--- once started fen-parse-helper does the recursion. What I'd like is a single routine that calls itself without the need to split across two functions. I think I'm nearly there, I just don't see the pattern well enough to implement it. I would reduce things to a skeleton but if I reduce too much I'll lose the solution when I build back up (at least that is what I'm worried about)
--hsm
Using a "helper" function is a common design pattern. They allow the use of another function as an iterator. You can define the helper function in a let-binding if you want to keep it hidden (let ((helper (lambda ...)))...). They are also often used when an accumulator argument is required in order to hide that from the caller (as a convenience).
Quote from: "Jeff"
Using a "helper" function is a common design pattern. They allow the use of another function as an iterator. You can define the helper function in a let-binding if you want to keep it hidden (let ((helper (lambda ...)))...). They are also often used when an accumulator argument is required in order to hide that from the caller (as a convenience).
I think this is what I was looking for. Could you expand?
That is the design you are using; a helper function that does the work and a main function which starts it running.
No, I mean the part about let-binding...
(let ((foo (lambda (...recursive call) ()))
(foo bar baz bat))