Comment/suggestion on improving the type for LispVal/LispError:
< augur> i dont know what you're doing with it tho
< pharaun> oh
< pharaun> data LispError = NumArgs Integer [Fix LispVal]
< augur> why?
< pharaun> instead of [LispVal s] its [Fix LispVal] so i remove the state
< augur> you need state in it tho
< pharaun> I flatten it
< pharaun> into a tree
< augur> eh.. you risk producing infinite trees that way
< pharaun> well its running now
< pharaun> but I can probably improve part of it
< pharaun> augur: yah, right now the flattening out part terminates early after a few loop
< augur> you should have some way to indicate you've stopped
< pharaun> I'll add that, good idea
< augur> it ought to be possible to error on a cyclic list, for instance
< augur> so you need something like..
< augur> data LispVal a = ... | Cycle
< pharaun> ooh
< pharaun> didn't think of that
< pharaun> >_<
< augur> and then Fix LispVal will put Cycle in place of the cyclic references
< augur> but you have to traverse the tree left-to-right
< pharaun> in the flatter i just terminated it with (String "<Terminated>")
< augur> because not all refs are cyclic
< augur> sometimes you have weird cross-references which arent obviously cyclic but which do lead to cyclicity
< augur> consider for instance a list analogous to this in haskell: let xs = (a, ys) ; ys = (b, xs) in (xs,ys)
< augur> its cyclic, but in a weird way -- the references go sideways, not obviously vertically
< augur> tho you could treat it like its just cyclic, you could also just block at the top ys
< augur> it depends on how much repetition you want, really, pharaun
< pharaun> augur: yeah right now i just terminate after a few step but yeah
< augur> pharaun: if you just treat it cyclically, you should print ((a,(b,...)),(b,(a,...)))
< pharaun> that would be much better
< augur> but you could also just print ((a,(b,...)),...)
< augur> pharaun: if you're really clever, you might even want to print something like
< augur> ( loop0: (a,(b,loop0)), loop1: (b,(a,loop1)) )
< augur> pharaun: that wouldnt be too hard, i dont think
< augur> pharaun: you'd have to do something like have an aux function that returns not just the printed val, but a list of refs that it
cut short due to looping, and then as you receive the returned list, you check if its the current ref, and if so you mark it
< augur> pharaun: this might be a good reason to have a custom type for flattened trees
< augur> pharaun: something like LispVal but recursive, and with extra constructors for cycle handling
< augur> pharaun: then you can write a function flatten :: LispVal s -> FlatVal
< augur> pharaun: in general its good practice to use data types to express intention :)
< augur> honestly i dont think you should parameterize LispVal at all, but
< pharaun> augur: don't i need to because of ST, cuz of LispEnv?
< augur> im not sure really. the purpose of the param is to sneak in the param of ST/STRef
< augur> pharaun: you might just be able to do LispVal s = ... | STRef s (LispVal s)