quickly finding a cons cell

Discussion in 'Cadence' started by Jimka, Apr 16, 2006.

  1. Jimka

    Jimka Guest

    Is there a clever way in SKILL to do somthing which sort of mixes
    the functionality of (foreach map....) with exists?

    I want the test applied to the cons cell, not to the car of the cons
    cell.

    As (foreach .... ) is to (exists ...)
    (foreach map ...) is to what?

    The exists function does not take an optional mapping function similar
    to foreach, but IF IT DID this is what i'd like to do.

    (exists map sub '(1 2 3 4 5 6 7) ((cadr map) > 3))
    ---> (3 4 5 6 7)

    What's the most efficient/fastest way to do this?

    -jim
     
    Jimka, Apr 16, 2006
    #1
  2. Probably:

    (prog ()
    (foreach map sub '(1 2 3 4 5 6 7)
    (when (greaterp (cadr map) 3) (return sub))
    )
    )

    I expect you can convert that into a macro yourself ;-> but here it is anyway:


    (defmacro abExistsExtend (mapFunc var lst @rest body)
    `(prog ()
    (foreach ,mapFunc ,var ,lst
    (when
    ,(if (cdr body) `(progn ,@body) (car body))
    (return ,var)
    )
    )
    )

    e.g.

    (abExistsExtend map sub '(1 2 3 4 5 6 7) ((cadr sub)>3))

    Regards,

    Andrew.
     
    Andrew Beckett, Apr 18, 2006
    #2
  3. I also just found this example that I wrote in 1999 - Jim, I suspect it was you
    that asked me this then, because I can't imagine anyone else asking it!

    /* exists_map.il

    Author A.D.Beckett
    Group Custom IC (UK), Cadence Design Systems Ltd.
    Language SKILL
    Date Nov 02, 1999
    Modified
    By

    A version of exists, which assigns the loop variable
    to the cdr of the list each time (like map).

    ***************************************************

    SCCS Info: @(#) exists_map.il 11/02/99.22:35:08 1.3

    */

    (defmacro exists_map (loop lst expr)
    `(let ((,loop ,lst))
    (while (and ,loop (null ,expr))
    (setq ,loop (cdr ,loop))
    )
    ,loop
    )
    )


    (defmacro exists_map2 (loop lst expr)
    `(prog ()
    (map (lambda (,loop) (when ,expr return(,loop))) ,lst)
    )
    )

    /* this one doesn't work...
    (defmacro exists_map4 (loop lst expr)
    `(let (_ret)
    (map (lambda (,loop)
    (when ,expr
    (setq _ret (cons (car ,loop) (cdr ,loop)))
    (rplacd ,loop nil)
    ))
    ,lst)
    _ret
    )
    )

    */

    ; when seems slightly faster in the loop - and and outside is faster!
    ; this version throws an error when it's done, which is caught for
    ; the return value
    (defmacro exists_map3 (loop lst expr)
    `(car (errset
    (and (map (lambda (,loop) (when ,expr (err ,loop))) ,lst) nil)))
    )

    (defun test_map ()
    (let (data)
    (for i 1 3000 (setq data (cons i data)))
    (profile 'time)
    ;(for i 1 1000 (exists_map3 x data car(x)<30))
    (for i 1 4000 (exists_map2 x data nil))
    (profileSummary)
    (profileReset)
    )
    )

    ; 3000 list, 4000 times, nil condition
    ; exists_map3 23.43
    ; exists 6.08
    ; exists_map 45.37
    ; exists_map2 23.39



    So looks like I did a fair bit of profiling at the time.

    Andrew.
    Andrew Beckett
    Principal European Technology Leader
    Cadence Design Systems, UK.
     
    Andrew Beckett, Apr 20, 2006
    #3
  4. Jimka

    Jimka Guest

    yes these are good solutions but the use of prog/return
    is not supported in scheme mode unfortunately... not sure
    why not but it is documented so.

    otherwise the other solutions seem to require that the entire
    list be traversed... or am i misreading it?
     
    Jimka, Apr 23, 2006
    #4
  5. Jimka

    Jimka Guest

    can the prog/return be replaced with some sort of goto? i know that
    go is supported in SKILL but i've never used it? Perhaps the macro
    could generate a label/go pair using gensym????
     
    Jimka, Apr 23, 2006
    #5
  6. Hi Jim,

    No, the other solutions I posted don't traverse the whole list - one uses a
    while/cdr loop - and stops when it reaches the match. The other uses errset/err
    to jump out.

    Andrew.
    Andrew Beckett
    Principal European Technology Leader
    Cadence Design Systems, UK.
     
    Andrew Beckett, Apr 24, 2006
    #6
  7. go() (yuck, I feel dirty even mentioning it) only works within a prog(), so that
    doesn't really help you..

    BTW, I tried the first solution (using prog/return) in SKILL++, and it worked.
    Perhaps prog() doesn't give all the lexical scoping advantages that let() does,
    so perhaps that's why it's not "supported" in SKILL++?

    Andrew.
    Andrew Beckett
    Principal European Technology Leader
    Cadence Design Systems, UK.
     
    Andrew Beckett, Apr 24, 2006
    #7
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.