Ah, you're right. I think jsgrahamus might be expecting result to be modified by this line:
(let (diagonals result row) (get-next-row board-size diagonals result)
..)
But it just creates a new shadowing binding for result, which exists only for the lifetime of the let, and is lost once the let is finished. Think of let as pushing a new value for its variable(s) on a stack before running its body, then popping the new values off, leaving behind any preexisting values.
Thanks, I'm familiar with that practice. I'm also used to passing by reference so that changes made to the variable in the newer function get passed back to the calling function.
Yeah, makes sense. However, let always creates a new binding and never modifies existing bindings. That's why it makes you indent its body to the right. Compare:
(= x 3 y 4)
(+ x y)
with:
(let (x y) '(3 4)
(+ x y))
The indentation is a hint that these are new x and y variables, compared to any earlier x and y variables.
Besides let there are indeed functions in Arc where you can pass lists or tables by reference (though not primitives like numbers or characters). However, it's usually a good idea to try to avoid these, again so you can practice a less imperative style of programming (http://arclanguage.org/item?id=19709). My usual approach is to first build a program with promiscuous copying everywhere, and then if it turns out to be too slow pick the 2% of cases that can speed it up a lot and make them destructive/call-by-reference, because the cost of doing so is that it makes the program harder to understand.
There's still other functions that are missing, such as goto-next-column, goto-previous-column, etc.
Anyways, I think you've gotten me to work on this problem as well :) I found it super hard when I solved it in C back in '97. Perhaps I should go back and see if I've gotten any better at programming.
So if two results were (2 4 1 3) and (3 1 2 4), both of them sort to (1 2 3 4) so delete one of them? Of course all of the results will sort to (1 2 3 4) for a 4x4 board.
Thanks! I think I'll try to solve it on my own without looking at yours in depth first. That might take me a few days. But feel free to keep asking questions in the meantime.
This took me too many hours in my work language to solve. Initially I next just translated it to arc, but that didn't seem to work, so I started again in arc from scratch. I sure learned a lot about arc and debugging in it.
It took me a while to wrap my mind around this problem. Sure is different than CRUD work, reports and interfaces.
My code snippet is doing that. The let is doing a sort of pattern matching and binding latitude to the first element of the result, and longitude to the second.
I thought that let looked odd, because I thought that with a let in arc, you had 1 variable/value pair. Thanks, zck, for pointing out the difference. And thanks, akkartik, for repeatedly telling me this.
As long as you use '=' it's easy to keep programming C or MUMPS in Lisp. Avoiding '=' forces you to give up old habits and become fluent with (writing as well as reading) deeply nested calls, 'let' and recursion. Those are some big reasons to use Lisp rather than imperative languages. So if you don't use them you're missing out.
Ah, thanks for spotting that so quickly. Arc warns when we replace a function with another. Perhaps it should also do so when we replace a function with anything else?
I did see it running momentarily on Windows a few weeks ago: http://arclanguage.org/item?id=19458. It might have a few issues, but if you report them I'll try to fix them.
Hey, one last-minute suggestion: suite-w/setup is a pretty long and ugly name. How about if we just always include a set of setup bindings in suite, even if they're empty? It would look nice and consistent with def and mac:
; without setup
(suite foo ()
(test must-bar
(assert-same 2 (+ 1 1)))
; with setup
(suite foo (a 1
b 2)
(test must-bar
(assert-same b (+ a a)))
I wouldn't be too disappointed if you decide against this, partly since it would save me the trouble of fixing my translator all over again :)
Interesting. I like the consistency. I don't love how it makes the most common case (I think the no-setup case is most common) and adds more code to it.
Maybe I can come up with a simpler, less awful thing.
Perhaps:
(suite foo (setup a 1
b 2)
(test must-bar
(assert-same b (+ a a))))
I'm kinda growing to like my idea the more I think about it. You're right that it adds 3 characters to the common case, but lisp has a long tradition of empty parens in various places. Saving characters shouldn't be a high priority, IMO. Paul Graham's notion of conciseness counts tokens, not characters.
But yeah, happy to see what other ideas we can come up with. I think the setup keyword above is worse; lisps don't tend to have keywords that aren't functions or macros. Then again, test is already a keyword that's not a function.. Hmm, I like it better if you indent it like this:
(suite foo
(setup a 1
b 2)
(test must-bar
(assert-same b (+ a a))))
The benefit of this approach is that it makes the syntax seem extensible. It's obvious how new features should be added.
I'm surprised by the redefinition warnings. They don't happen for me. Perhaps you have some of your own code being loaded? Or maybe you have an old version? (Though I don't remember make-list ever being a thing.)