local scope functions

Discussion in 'Cadence' started by fogh, Jul 23, 2004.

  1. fogh

    fogh Guest

    Hi All,

    Does anyone know how I can define functions locally ?
    I would need something like a letfun() macro that will unbind the function outside the letfun()
    In skill,that is. I suppose it is easy to do in skill++
     
    fogh, Jul 23, 2004
    #1
  2. Frederic,

    This is exactly what SKILL++ is for. I suggest you do it in SKILL++ rather
    than trying to find a tortuous way of doing it in SKILL. In SKILL you can assign
    function objects to variables in let statements:

    let((mylocalFunc)
    myLocalFunc=lambda((arg list) body...)
    ; and then call them using funcall:
    funcall(myLocalFunc arg1 arg2)
    )

    but in SKILL++ it's cleaner:

    let((local vars)
    procedure(myLocalFunc(arg list) body...)
    ; and then call them
    myLocalFunc(arg1 arg2)
    ) ; let

    For a quick intro to SKILL++ look at my article:

    http://sourcelink.cadence.com/docs/files/FFF/199/skillpp.html

    Regards,

    Andrew.
     
    Andrew Beckett, Jul 24, 2004
    #2
  3. fogh

    Jim Newton Guest

    Hi andrew, perhaps an flet macro would be useful as part of SKILL++.
    This would hide the lambda...

    flet( myLocalFunc1( ( arg list) body ...)
    myLocalFunc2( ( arg list) body ...)
    ...
    )
    ...
    myLocalFunc1( ...)
    ...
    myLocalFunc2(....)
    ...

    )
     
    Jim Newton, Jul 25, 2004
    #3
  4. Jim,

    But in SKILL++ the lambda is hidden if you use the:

    let(()
    procedure(myLocalFunc1(...) ...)
    ...

    )

    approach. Any functions defined within the let are automatically made local
    variables within the let.

    So I don't see much benefit in having flet() over ordinary let() in SKILL++

    Just my $0.02...

    Andrew.
     
    Andrew Beckett, Jul 26, 2004
    #4
  5. fogh

    fogh Guest

    Andrew,

    There is in the double-click code I sent before an example of a need for a local function that has been bound as a function. I need a named function only to satisfy gePointQuery 's way of taking "filter" functions, but I want to throw it away after that.
    BTW, It would be nice that the gePointQuery function accepts either a string or a funobj for the filter

    It does not really do what
    somefunc=lambda(nil t)
    => funobj@someadress
    boundp 'somefunc
    => t
    fboundp 'somefunc
    => t
    After reading it, I tried to use skill++ in this way:
    toplevel('ils)
    let(()
    procedure(mythrowawayfilter(arg) ...)
    ....
    gePointQuery( arg1 arg2 "mythrowawayfilter")
    ....
    );let
    resume()

    But it seems my procedure does not "finish" properly, I still have a prompt of "ILS".

    Call me stubborn,but...would foresee any problem with a letfun(arg1 argrest) macro that would unquote argrest and then do something-like
    mapcar(lambda((f) putd(f nil) ) arg1)
    ?
     
    fogh, Jul 26, 2004
    #5
  6. fogh

    Rob Peters Guest

    Frederic,

    I used the local function with the lambda binding for years already. It is
    not necessary to 'funcall' the local function. You can use the local
    function as a normal function within a function.

    So:

    let((mylocalFunc)
    myLocalFunc=lambda((arg1 arg2 ...) body...)
    ; and then call it as usuall
    myLocalFunc( arg1 arg2 ...)
    ; or
    test = myLocalFunc(arg1 arg2 ...)
    )

    Untested but I guess it will work, you can use again 'let' to define local
    variables within the local function body (and define again local
    functions!)

    See the skill language user guide, 'advanced topics', 'assigning a New
    Function Binding' to get an idea.


    Rob Peters
     
    Rob Peters, Jul 26, 2004
    #6
  7. Hi Frederic,

    This won't work even if you use SKILL++. The reason is because gePointQuery
    expects a function name, and is evaluated in the global scope - so it wouldn't
    find a locally scoped function.

    The solution would be if it accepted a function object, as you say. The trouble
    is that this function pre-dates when function objects were created by SKILL.
    However, it could be retrofitted.

    Log a service request, and this enhancement can be requested.
    You can't put toplevel('ils) and resume() in code files - it doesn't work like
    that. toplevel starts a new top level. The best way to have SKILL++ code is
    to give the file a .ils suffix. If you just want to use SKILL++ for a smal
    region of code, you can use:

    inScheme(
    let(()
    procedure(myLocalFunc(...) ...)
    ...
    ) ; let
    ) ; inScheme

    But that's not going to help here.
    But the putd wouldn't make it local. It doesn't work like that. Each symbol in
    SKILL has a function slot, a value slot, and a property list slot. The value
    slot is effectively a stack (which is how dynamic scoping in SKILL is
    implemented). However, the function slot is a single global slot.

    In SKILL++ you have the concept of environments, which contain variable
    bindings. When you define a function, it has associated with it the lexical
    environment in place at define time. Then when you call the function, it
    restores the environment which was there at definition time, so variable lookup
    is lexically scoped (this is rather an abbreviated definition). Functions are
    stored as variables (in essence), so a function call just looks up the
    function object in the variable with the same name as the function call, and
    then calls that.


    Regards,

    Andrew.
     
    Andrew Beckett, Jul 27, 2004
    #7
  8. Rob,

    I'm sorry, but this doesn't work with SKILL. I don't know why you think it does.
    I'm prepared to be surprised, but I can't see how this can work in SKILL.

    With SKILL++, it would work (do you have a .ils suffix for your source files?).

    From the manual reference you give, I assume you're actually doing:

    let((myLocalFunc)
    putd('myLocalFunc lambda(....))
    myLocalFunc(args)
    )

    However, the putd() would not be storing a local function definition. As I
    mentioned in a previous post, the function slot of a symbol is global. And
    putd writes into the function slot, and so the function is global. In SKILL,
    the function slot and value slot of a symbol are distinct.

    Andrew.
     
    Andrew Beckett, Jul 27, 2004
    #8
  9. fogh

    Jim Newton Guest

    Hi andrew, how should i define functions which
    i only want to be visible inside another function?
    whould i define them with let/setq or with
    procedure?

    defmethod( mymethod ()
    procedure( (myLocalFunc1 arg1 arg2) ...)
    procedure( (myLocalFunc2 arg1 arg2) ...)

    ...
    let( ( x y )
    x = myLocalFunc1( 1 2)
    y = myLocalFunc2( 3 4)
    myLocalFunc1( x y)
    ))

    Or should I put the procedure definitions inside the let?
    And should I declare myLocalFunc1 and myLocalFunc2
    inside the let?

    Or should i declare the variables myLocalFunc1 and myLocalFunc2
    and assign their values with lambda?

    defmethod( mymethod ()
    let( ( myLocalFunc1 lambda( ( arg1 arg2) ...))
    ( myLocalFunc2 lambda( ( arg1 arg2) ...))
    x
    y )
    x = myLocalFunc1( 1 2)
    y = myLocalFunc2( 3 4)
    myLocalFunc1( x y) ))

    I suspect that if i put the procedure inside the function def
    it is more computation intensive in that it redefines
    the procedure everytime the function is called, but that
    somehow the lambda is optimized. Is that true or are
    they equivalent?

    -jim
     
    Jim Newton, Jul 28, 2004
    #9
  10. fogh

    fogh Guest

    Rob,
    it doesn t work for me:
    let( (mf) mf=lambda(nil printf("Hi, galaxy.\n")) mf() )
    gives an
    "error eval: undefined function mf"

    Do you use an environment where = is overloaded or are you doing skill++ ?
     
    fogh, Jul 28, 2004
    #10
  11. fogh

    Rob Peters Guest

    Andrew,

    Thanks for explaining this miss-understood 'local' function definition: it
    is global indeed. I used the putd construction as you said. (It was
    difficult
    to remember code at home while answering this newsgroup).

    I tested the putd/lambda construction in the past but I made a mistake of
    not testing the 'local' function construction after executing the parent
    function. Now I did and found the 'local' function defined global.

    Lucky I had always a putd construction in all my code to 'redefine' the
    global function slot. That's why I never noticed misbehaviour of different
    function bodies with the same name. But if I had used a name already in use
    then ... Because the names were thought local I did not use prefixes in
    front
    of the used names, that saved me!

    I will scratch this dangerous construction from my programming cookbook but
    will remember skill++

    Rob


     
    Rob Peters, Jul 29, 2004
    #11
  12. Hi Jim,

    You can put them inside a defmethod() or a procedure(), and
    they will be local. Put here, they seem to be created locally, but they don't
    seem to have the method or procedure's argument list in their
    lexical environment though (I've not experimented enough).
    I must admit, I never create local functions this way in my code, so I've not
    really played with this form enough (except just now to try it out).
    That's indeed what I would always do - put the procedure definitions within the
    let. There is no need to list the procedure names in the list of local variables
    for the let - this gets done automagically by SKILL++.
    You can do this, but there's no particular benefit in doing so.
    It does not redefine the procedure every time you call the parent method or
    function.

    You should be aware that you can't put defmethod() or defgeneric() within a
    let() and expect these to be local - the CLOS aspects of SKILL++ don't entirely
    mix smoothly with the scheme aspects - so you can't have local classes and
    generic functions; these are always global.

    Regards,

    Andrew.
     
    Andrew Beckett, Jul 30, 2004
    #12
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.