• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Community Forums
  2. Custom IC SKILL
  3. Scheme version of apply

Stats

  • Locked Locked
  • Replies 5
  • Subscribers 142
  • Views 14362
  • Members are here 0
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Scheme version of apply

AurelBuche
AurelBuche over 5 years ago

Hi all,

I am trying to define a local lambda where arguments structure is coming from the output of another function

to simplify i have something like:

(inScheme
(let ((b 12))

  (defun make_args nil
    '(@optional a))

 ((apply lambda (make_args) (plus a b) nil) 27)

);let

);inScheme

which should be returning 39 but raises an error because the call to apply switch back to dynamic scoping

I know I could do something similar using eval and theEnvironment but this is exactly what I am trying to avoid

Is there a way to keep the lambda call into my closure without using eval?

Cheers,

Aurélien

  • Cancel
  • Andrew Beckett
    Andrew Beckett over 5 years ago

    Hi Aurélien,

    It's not really clear what your end goal is (I'm assuming this is just a cut-down example to illustrate the problem), but fundamentally the issue is not with apply here - it's the fact that the function object created by the lambda (on the fly, at run time) is being created outside of the lexical environment. There's a small typo in your code - it should have been ((apply lambda (make_args) '(plus a b) nil) 27) because otherwise it would have been trying to do the addition before the function is created, and clearly a would have not been in scope then. However, even with that correction, it still doesn't work because the variable b is not in scope when the resulting function object is called, because it's been created in the lexical environment.

    Since you are actually creating a new function object at run time, there's really no disadvantage to using eval here - in either case it's going to have to do the function creation and compilation. So this will work:

    x=(let ((b 12))
    
      (defun make_args nil
        '(@optional a))
    
      ((eval `(lambda ,(make_args) (plus a b)) (theEnvironment)) 27)
    
    );let

    Having chatted about this with my team, we suspect that there might be a more elegant solution to your problem if we knew what you're really trying to do rather than this rather abstract example. That said, if you are creating code at run time, there isn't really an alternative to using eval - and that's precisely what it's useful for.

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 5 years ago in reply to Andrew Beckett

    One other little thing - we noticed that in your post (and one of your previous posts) you used the inScheme macro. I assume you're aware that if you put the code in a file with the .ils suffix (or .ilse these days, to provide a suffix for encrypted SKILL++ code) then it is read using SKILL++ (Scheme) semantics? I tend to minimise the use of inScheme to just places where I temporarily need to access something with SKILL++ semantics (or SKILL++ variables) in a larger piece of traditional SKILL code.

    Maybe you just did this for clarity, rather than being part of your normal coding practice?

    Andrew

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • AurelBuche
    AurelBuche over 5 years ago in reply to Andrew Beckett

    Yes, I usually don't use inScheme,

    it's just to make the use of SKILL++ obvious in my code snippet

    (I don't want people trying to figure out why my code is not working in their CIW which is usually in a SKILL top level,

    even though it won't in this case due to the typo and the scope error

    I wrote it on the fly to make a simple example but I haven't really tried it as I already had the error)

    You have my attention with the more elegant solution you are talking about so I'll try to synthesize what I am trying to achieve in a next answer

    Cheers,

    Aurélien

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • AurelBuche
    AurelBuche over 5 years ago in reply to Andrew Beckett

    I am currently working on a set of very high-level functions that I want to write using specific custom functions
    (many reasons to do that, there is mainly an object oriented architecture behind but I don't want to go further in details as it is not the main point)

    Each of my function is contained in its own file that looks like this (this is a dummy example):

    ;; my_function.ils
    (custom_set_function_doc    "Place a square of LAYER")
    (custom_set_function_author "A. Buchet")

    (custom_set_function_name   'my_function)
    (custom_set_function_label  "My Function")

    (custom_set_function_param
      ?name 'layer
      ?type 'layer
      ?defValue 'M1
      ?doc "Symbol representing a custom layer"
      )

    (custom_set_function_param
      ?name 'width
      ?type 'float
      ;; Layer should be available here as it was defined above
      ?defValue '(custom_get_minimum_width layer)
      ?doc "Width of the place square"
      )

    ;; Macro to avoid evaluating given code
    (custom_set_function_body_q
      (dbCreateRect (geGetEditCellView)
        (custom_get_lpp layer) (list (list 0 0) (list width width)))
      )
    ;; end of my_function.ils

    This file should be loaded with a custom procedure
    It should generate a SKILL++ function object looking like this:
    function->??
      (doc "Place a square of LAYER"
        author "A. Buchet"
        name my_function
        label "My Function"
        parameters ...
        body (dbCreateRect (geGetEditCellView)
               (custom_get_lpp layer) (list (list 0 0) (list width width)))
        )

    and ... in parameters is a list of objects as well


    function->parameters~>??
    (
      (name layer
        type layer
        defValue M1
        doc "Symbol representing a custom layer"
        )
     
      (name width
        type float
        defValue (custom_get_minimum_width layer)
        doc "Width of the place square"
        )

      )

    From this I want to be able to generate different functions:
    It could be without the body but just debug messages in case of a dry run
    It could be the classic one with just the body
    The same with the body and the debug messages
    Another one where I check each parameter type
    etc.

    In my case I may have different bodies, in case I am generating a layout object
    or it's associated constraints

    But I want those functions to have the same arguments structure, in the previous case it should
    be:

    (lambda ((layer 'M1) (width (custom_get_minimum_width layer)))
      ...
    )

    I managed to make this work using apply but in dynamic scope arguments cannot be dependent to each other

    eval will do the trick but if you have a more elegant solution I am all ears

    Cheers,

    Aurélien

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 5 years ago in reply to AurelBuche

    Hi Aurélien,

    My team had a chat about this - it appears you're effectively creating a new mini-language, which is often (usually) achieved using macros, although if it's done carefully, eval is perfectly reasonable too. It's not clear where the actual function objects are being created in your example (you don't show how they're being called), but I can see that you could create them with eval and even cache them to avoid creating them every time you call the function.

    I'm not sure why you think that apply is only in dynamic scope - that's not true. apply can perfectly well be used in a lexical scope - the issue before wasn't the apply, but the fact that creating  a new function object using apply and lambda doesn't get created within the lexical environment - and eval is a perfectly reasonable alternative to that. However, if you can avoid creating a new function object each and every time you call the function, then that's a good thing to do.

    BTW, if your system is objected-oriented, why not use the SKILL++ object system?

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information