[racket] Rosetta Sokoban Solution
It doesn't have to be exactly PicoLisp. I would be happy with a thin
wrapper library that simply translates super-long-names into names.
Define being called "define" because it equals the English spelling
isn't too compelling or else German programmers are in trouble. define
is definieren. I imagine define-syntax-parameter is
definieren-schalggendlahg-paravolddennneinen and they probably use 230
width margins as a default...else they don't use full words. In Pico,
define = de. Many newish languages use def. Haskell goes off of
formatting and "=" (a single character is about as good as it gets...).
Arc's print = pr, etc. It's not good when a /functional/ language's
main function-defining-construct takes the same total characters as 3
other languages combined (def+de+=).
The following is halfway about Racket conventions/style, halfway about
pattern matching is evil (esp. without type inference), and is mainly me
rambling, so be advised...
I have thought further about mixed data and verbosity, and I believe the
fundamental issue is static typing, the lack of, and trying to simulate
it with fancier types (at the expense of verbosity). Mixed data without
static types thus has the verbosity downside but without the
hypothetical safety upside...the struct amounts to a built-in /comment/
about what is supposed to be its data, but it's really just a list with
lengthier access functions and lack of list-powered functions to operate
on it. Lack of static typing means (struct pos (x y)) sure looks like
something that contains numbers but in untyped Racket it's really just
(list any/c any/c), without the ability to treat it as a list. So
something like e.g. distance from 0 in the moves on a square grid sense is:
(+ (pos-x p) (pos-y p))
instead of:
(apply + p)
which really should be:
(app + p)
Then, if you change the struct, your code is secretly wrong everywhere
you pattern match. One is "supposed" to abstract with functions. In
SICP it's a given that accessors are in terms of caadaaar and such,
versus relying on the fact that it's actually /at/ the position referred
to by caadaaar, exactly what pattern matching does. Many example
problems for the purposes of demonstrating the value of abstraction have
the reader redefine the datatype, requiring changes to /only/ the
accessors, say cadaar instead of cdadar. Pattern matching undoes this
advantage and the programmer is in a situation where every usage of the
struct must be tracked down or suffer runtime errors. This disadvantage
is minimized with static typing and type inference. Haskell can tell
you that either 1. a String is not an Int within some ADT or that 2.
there aren't enough positions matched against in the first place. The
syntax is also superior:
(match-define (cons (pos x y) ps) ps0
versus, in Haskell:
(Pos x y):ps' = ps
Or in "short Racket":
(mdef (cons (cons x y) ps) ps0
or even:
(mde ((x.y).ps) ps0
and we're at half the length of normal Racket, or:
caar, cdar, and cdr respectively to compose the "struct" access
functions with the list ones with the addition of a single letter (caar
vs. (compose pos-x car)), or, lastly, to be fully SICP compliant, using
names that the struct maker in Racket would've come up with, except
potentially much shorter than the auto-generated ones. I'm aware these
can be renamed, but there's still the disadvantage that structs aren't
lists.
As for going pure cons, I don't believe caar is a spaghetti code version
of the pattern match above. In the programmer's mind x has to be
constantly thought of as the most recent position's x coord all the way
through the section where it's in scope, or else he can't be using it
correctly. He must know what x really/is/, not /where/ he got it from.
Pattern matching emphasises the /where/. It's semi-necessary though in
supposedly good coding style because the struct "should" have a solid
name like item and fields with solid names like "weight", meaning that
accessing a couple things is:
(item-weight i)
(item-value i)
etc.
instead of:
(car i)
(cadr i)
This verbosity encourages the use of the matcher,
(define-match (item w v) i
Yet that is nearly as long in total character length as the long
accessors thanks to deeffiinnneee-maaattchhh, and forever ties w to
whatever happens to be in the left-most position.
Pattern matching issues aside, I believe Racket could benefit from
chopping 50% of the letters out of its identifiers.
list-ref = nth
define = def
define-values = defs
define-X = def-X
apply = app
vector-set! = vec!
set-box! = box! (in general, the "!" indicates a setter, so do away with
the "set-")
print = pr
display = disp
string-X = str-X
append-map = map* / mappend / mapp
null? = nil?
lambda = delete entirely, because pressing ctrl+\ and getting an actual
lambda is vastly superior, or replace with "\" to keep it simple
On 06/10/2013 02:28 PM, Matthias Felleisen wrote:
>
> On Jun 10, 2013, at 1:49 PM, Sean Kanaley wrote:
>
>> But if I had to choose which language seems to actually produce
>> better code, I would have to side with PicoLisp.
>
> I wonder whether we could implement pico as a language and then write
>
> #lang racket/pico
>
> and just reuse the PicoLisp code.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20130610/a0ec2910/attachment-0001.html>