Arc Forumnew | comments | leaders | submitlogin
(delist somelist)
4 points by bOR_ 5823 days ago | 22 comments
I'm missing something simple, but I've a list of lists that I want to sum.

I have this:

  (map + (list (list 1 2) (list 3 4)))
and I want this:

  (map + (list 1 2) (list 3 4))
Is there any simple function that breaks down a list into its components (I know each does, but not how to simple apply it here). I've also tried to consing + and map to the list of list, and then evaluating it, but without much success ;)


4 points by jmatt 5822 days ago | link

Just to summarize: The simplest answer to the post is:

  (apply map + your-expression)
or

  (apply map + (list (list 1 2) (list 3 4)))
This solution was provided by almkglor

-----

2 points by Darmani 5823 days ago | link

A month or two ago, I wrote Sokoban in Arc, and produced a small library for multidimensional lists in the process. This function should interest you:

  ;dims needed because ((abc)) may be a two-dimensional list containing abc or 
  ;a one-dimensional list containing (abc)
  (def muldim-map (dims f lst)
    ((afn (lst)
      (if (no lst)
        nil
        (if (is dims 0)
          (f lst)
          (cons (muldim-map (- dims 1) f (car lst)) (self (cdr lst))))))
      lst))

-----

1 point by bOR_ 5823 days ago | link

If I read it right, it is a function that for example, can grab the nth entry from a cell (or nth row / column from a matrix)?

You have the code out there somewhere? It is probably good to have some more examples of Arc out in the open, and there'll be things in it I can learn from.

-----

1 point by Darmani 5823 days ago | link

Sorry, I misunderstood your query last night.I just realized the function actually doesn't apply in this specific instance here.

It's a version of the normal map generalized to n-dimensional lists; I forgot when writing it that normal map accepts multiple lists.

However, with that added, it would be useful if you, say, had (((1 2) (3 4)) ((5 6) (7 8))) and wanted ((6 8) (10 12)); that would end up being (apply muldim-map 2 + (list (list (list 1 2) (list 3 4)) (list (list 5 6) (list 7 8))))

(I was going to download Arc's source code and use the source of the original map as a guide to writing a version of muldim-map that could handle multiple multi-dimensional lists on the spot, but I don't believe these high school computers have software that can handle tarballs.)

-----

2 points by Darmani 5822 days ago | link

However, I just realized I had another function in that library that could perform the task you described, although it would be overkill. It's called something like move-muldim-block; it takes a multi-dimensional list and returns a new multi-dimensional list with a multi-dimensional piece of that list moved elsewhere, using a combining function to determing the value of the area in which it was moved (I used it in Sokoban to simplify code that would let let me move a crate character onto a storage character and change it to the crate-on-storate character).

In other words, if lst is set to ((1 2) (3 4)) and f is some function, (move-muldim block (list 1 0) (list 1 2) (list 0 0) +) would be equivalent to (((+ 1 3) (+ 2 4)) ((f 3) (f 4))) (it moves a 1x2 block from coordinates (1 0) to coordinates (0 0)). Just take the car of the result and you have what you're looking for (in which case, we could omit the last argument and use the default value).

For this specific task, apply is a heck of a lot simpler, but I can still post the code if you're interested. I personally found it very interesting to realize that this could be done, and that muldim-move-block is a little more useful than I first thought.

-----

1 point by bOR_ 5822 days ago | link

Hmm. Right now I store the positions of my mobile piec elsewhere than in the world-list. Your function might be handy later on. I haven't yet decided if I want every actor of the world stored in the world (even if some of them might overlap), or store the mobile actors in a separate list.

Right now the thing about sokoban implementations that would interest me most is if you've done anything fancy to generate the output. Having an update of a 2d world scroll by ever so often makes it hard to track movement of a single character through this world. Did you work on that?

-----

3 points by almkglor 5822 days ago | link

Since Arc is a language targeted for the web... have you considered the possibility of generating a web page for it, with maybe next >> and << prev links?

-----

1 point by bOR_ 5822 days ago | link

That might actually work, and just autorefresh the page every second or so :)

First priorities now are finishing the wandering algorithm for the animals so that they're no longer steered but steer themselves, and generalize the code I've some more so that adding more behaviours than just biting things is easy. I'll add the visuals-through webpage idea to that list :)

-----

1 point by Darmani 5822 days ago | link

Sorry, not really. I just used a simple function to print out a 2-dimensional list and resized my terminal window so that the grid would be in the same place after every sequence of moves, which gives the illusion that the same grid is being redrawn.

-----

1 point by Darmani 5822 days ago | link

Small mistake -- the invocation would be (move-muldim block (list 1 0) (list 1 2) (list 0 0) + f) (I hope no-one thought I'd be silly enough to set the function to find the replacement-fn by looking up the global value of f...).

-----

2 points by jmatt 5823 days ago | link

(flat (list (list 1 2) (list 3 4))) will do it.

I've used flat before and it's worked well.

reference: http://www.arcfn.com/doc/list.html

-----

1 point by bOR_ 5823 days ago | link

Hmm. Seen flat and tried it. in Arc2 flat works recursively, turning (list (list 1 2) (list (1 2)) into (1 2 1 2), which doesn't produce the desired (2 4) when combined with map +

  (map + (flat (list (list 1 2) (list 1 2))))
  (1 2 1 2)

-----

9 points by almkglor 5823 days ago | link

  (apply map + your-expression)

-----

3 points by bOR_ 5823 days ago | link

  (apply map + (map vals:craa!eltm:car (observecone craa!pos (list 0 359) craa!range)))
  (122 31 0)
Thanks! I'll digest what things you can do with the apply map combination in my sleep, but it seems quite handy.

-----

2 points by absz 5823 days ago | link

The apply function takes a function, any number of arguments, and a list, to wit (apply f x0 x1 x2 ... xN args). This is the same as (f x0 x1 x2 ... xN args.0 args.1 args.2 ... args.M). This allows you to construct argument lists at runtime, which can come in very handy.

-----

2 points by jmatt 5823 days ago | link

almkglor nailed it.

That's elegant and simple.

-----

1 point by bOR_ 5804 days ago | link

Different problem, similar question.

rand-choice returns one of its arguments. Can it also pick one of the arguments in a list?

  (rand-choice (list 1 2 3)) 
gives (as per expected)

  (1 2 3)
and to pick a random value of a list I currently use

  (let mylist (list 1 2 3)
     (mylist (rand(len mylist))))
Scanned through arcfn.com, but didn't spot anything that turns a list into a number of arguments, so that it can be fed to rand-choice

  (rand-choice (delist mylist))

-----

2 points by almkglor 5804 days ago | link

'apply

  (apply rand-choice (list 1 2 3))

-----

2 points by bOR_ 5803 days ago | link

Had tried apply, but that doesn't work in arc2. I get a

  "Function call on inappropriate object #3(tagged mac #<procedure>) (1 2 3)"
Might be inevitable for me to move over towards anarki, if it works there. :P

-----

3 points by absz 5803 days ago | link

Actually, in looking over the functions again, it turns out that there is already a function that does what you want: random-elt. That should do what you need it to do.

As for your problem (and no, it doesn't work on Anarki[1]), the problem is that rand-choice is a macro, not a function, and apply only works on functions. The only solution is a terrible hack:

  (def mapply (macro . parms)
    " Applies the macro `macro' to `parms', which are not quoted.
      See also [[mac]] [[apply]] "
    (eval:apply (rep macro) (join (butlast parms) (last parms))))
But don't use that!

[1]: But you should use Anarki anyway :)

-----

2 points by bOR_ 5803 days ago | link

Thanks for the reminder not to apply on macro's, and for finding random-elt. I need to learn how to read ;).

random-elt does exactly what I want.

(btw.. small consistency issue in the syntax here?) rand-choice random-elt

-----

1 point by absz 5803 days ago | link

To further clarify, if you've programmed in Ruby or Python: (apply func ... arglist) is equivalent to func(..., * arglist) in those languages.

-----