Arc Forumnew | comments | leaders | submitlogin
1 point by Darmani 6078 days ago | link | parent

  (= range cons)

  (def within (range num)
    (and (>= num (car range)) (<= num (cdr range))))

  (def directawayfrombounds (creature)
    (let awaydir (fn (pos dim dir)
       (if (within (range 0 (- dim 1)) (+ pos dir))
         dir
         (- dir)))
      (list 
        (awaydir (car creature!pos) (len (car world)) (car creature!dir))
        (awaydir (cadr creature!pos) (len (car world)) (cadr creature!dir)))))


1 point by almkglor 6078 days ago | link

'range is an arc.arc function in canonical Arc, so you should be leery of redefining it - if you decide to use some random library, and it uses 'range in the canonical sense, you can expect it to break.

Instead, define it in subfunction form:

  (def directawayfrombound (creature)
    (withs (range
              cons
            within
              (fn (range num)
                (let (min . max) range
                  (<= min num max)))
            awaydir
              (fn (pos dim dir)
                (if (within (range 0 (- dim 1)) (+ pos dir))
                    dir
                    (- dir)))
            (xpos ypos) creature!pos
            (xdir ydir) creature!dir)
      (list
        (awaydir xpos (len world.0) xdir)
        (awaydir ypos (len world.0) ydir))))

-----

1 point by Darmani 6077 days ago | link

Thanks for the correction. Although I did know about the canonical range function, it slipped my mind when I wrote that (though I did have the feeling that there was a "real" range function). I should have mentioned that I wasn't near any computer with Arc when I wrote, though I still should have known better.

-----

1 point by bOR_ 6078 days ago | link

Both of you, thanks!, more learning arc. (1) "withs" is "with sequentially"', so that "range" makes sense in the function "awaydir". (2) cons isn't just appending a number to a list.

I like the table!key syntax, not sure what I'm thinking about world.0 as a syntax, especially because world.0.0 doesn't give what I'd expect (first element of the first element of world), but just returns the same as world.0

  (def makeworld (x)
     (= world (n-of x (n-of x nil))) ; world of nil
     nil)

-----

1 point by Darmani 6077 days ago | link

Actually, almkglor's code would (I'm pretty sure) have worked with just a normal with; function definitions are unevaluated at definition, so that (fn (x) (afergergghersgergferg x)) would not give "Error: afergergghersgergferg is not a function" until it's called. If a defined a function called afergergghersgergferg in the meantime, as with a normal with statement, it should have worked.

Anyway, you're not alone in being surprised that x.y.z expands to (x y z) instead of (x (y z)).

-----

2 points by absz 6077 days ago | link

Not quite. It works in the toplevel because doing (def name args ...) is effectively to (= name (fn args ...)); this establishes a global, not a lexical, binding. Using let/with/withs adds a lexical binding, and since functions (or "closures") close over their scopes, they can't get at functions defined at the same time. Thus, you need to use withs. Observe:

  arc> (with (foo (fn (x) (* 2 x)) bar (fn (y) (foo y)))
         (prn (foo 10))
         (prn (bar 10))
         t)
  20
  Error: "reference to undefined identifier: __foo"
  arc> (withs (foo (fn (x) (* 2 x)) bar (fn (y) (foo y)))
         (prn (foo 10))
         (prn (bar 10))
         t)
  20
  20
  t

-----

1 point by bOR_ 6077 days ago | link

That implies that at the top level, the order in which I define my functions (which use each other) doesn't matter..

nice! Then I can group them in a way that is more sensible for humans.

Anyway, the program is now far enough that I've a critter running around the field and filling its memory with associations between the things it encounters. Next stop is to let it learn what is edible and to let it steer itself based on its observations :).

-----