• 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. nconc with (back)quote'd list constants

Stats

  • Locked Locked
  • Replies 11
  • Subscribers 144
  • Views 4498
  • 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

nconc with (back)quote'd list constants

tweeks
tweeks over 11 years ago

Google says: "Avoid nconc!"

http://google-styleguide.googlecode.com/svn/trunk/lispguide.xml#Avoid_NCONC

They recommend to use "mappend" instead, which you could naively define this way (naive because it's O(n^2)!):

(defun mappend (fn list "ul")
  "Append the results of calling fn on each element of list.
  Like mapcan, but uses append instead of nconc."
  (foldl1 append (mapcar fn list)))

(defun foldl1 (function list "ul")
  (if (null list)
      (error "foldl1: empty list")
      (foldl function (car list) (cdr list))))

(defun foldl (function initial list "ugl")
  (let ((result initial))
    (foreach mapc element list
      (setq result (function result element)))
    result))

If you don't see the danger, try this:

ILS-> (mappend (lambda (x) '(t)) '(1 2 3))
(t t t)
ILS-> (mapcan (lambda (x) '(t)) '(1 2 3))

The mappend version works correctly, but the mapcan version sends the interpreter into an infinite loop! 

Explanation: mapcan applies the lambda to 1, and nconcs the result--the constant '(t) list returned by the lambda--to itself, resulting in a circular list of length one, where the car is t and the cdr is its own car.  The next iteration, mapcan applies the lambda to 2, only this time nconc never returns, because it's too busy trying to find the end of an endless list....

I guess I'll have to write my own (foreach mappend....) to use in place of the more dangerous (foreach mapcan...).

  • Cancel
Parents
  • tweeks
    tweeks over 11 years ago
    Andrew Beckett said:

    Oh, and by the way, I always recommend against defining your own "core" functions without prefixes, unless they are in (say) a lexical scope where you can see the definition too. The reason is that for a casual reader, they look like standard functions - and secondly if Cadence then defines a core function which happens to have the same name, your code will break...

    In your example, you used a function foldl1.

    Yes, that code originally lived in a lexical scope (my own personal module system), and I totally forgot it was unprefixed!

    This reminds me of a broader philosophical issue, however.  One feature of Lisp that has gathered much praise over the decades is how functions defined by the programmer look and feel just like functions built into the language.  Without closer inspection, you wouldn't know that fold1 wasn't a SKILL primitive operator.

    I always hear this being described as an advantage, adding to Lisp's flexibility and expressiveness.  However, in systems like Emacs and Virtuoso that lack package/module systems, there is a strong push in the opposite direction, for programmers to name their functions in a conspicuous manner (i.e. with "user" prefixes) so as to avoid inadvertently clashing with builtins!

    I have mixed feelings about this.  In the absense of modules/packages, prefixing makes sense from a maintenance point of view.  However, prefixing destroys that sense of smoothly extending a core language, because SKILL functions all look likeThis(), but my functions have to look CCFlikeThis(), with big ugly capital letters on the front. 

    If I want to add some Common Lisp primitives like "first", "second", "third", etc. to SKILL, I technically ought to name them "CLfirst", "CLsecond", "CLthird", ....   The point is to make SKILL look more like CL, but the effort is largely nullified by putting capital CL at the beginning of everything.  (Emacs has the same problem: cl-first, cl-second...  At least it's lowercase.) 

    I guess there's no point in trying to make SKILL look like another dialect, because such an effort can never be 100% successful without writing a full interpreter.  However, SKILL itself has added gratuitous primitives to its core to make itself look more like Scheme!  For example, eq? is exactly like eq.  Why do we need both of them?  If you're willing to add eq?, why not add zero?, one?, number?, positive?, and procedure? as well?  I sense a half-hearted attempt at Scheme-compatibility.  Everyone knows SKILL++ can never be 100% compatible with Scheme, so why did they even try?  Why flood the namespace with redundant Schemey names for the Maclispy/Common Lispy primitives SKILL inherited from Franz Lisp?  I even made a list of them all:

    boolean? (obj)

    define (g_general g_general \@optional g_general \@rest g_general "ggg")

    eq? (g_general g_general "gg")

    equal? (g_general g_general "gg")

    eqv? (g_general g_general "gg")

    even? (g_general "g")

    for_each (u_function l_list "ul")

    integer? (g_general "g")

    list? (g_general "g")

    negative? (g_general "g")

    null? (g_general "g")

    odd? (g_general "g")

    pair? (g_general "g")

    real? (g_general "g")

    set! (s_symbol g_general "sg")

    set_car (l_list g_general "lg")
    set_cdr (l_list l_list "ll")

    setcar (l_list g_general "lg")
    setcdr (l_list l_list "ll")

    symbol? (g_general "g")

    symbolToString (symbol "s")

    vector? (g_general "g")

    All of these are redundant names.  If you are going to add all the IEEE Scheme names for things, you should at least finish the job!  Will the remaining primitives ever be added?  Why even bother anyway?

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Reply
  • tweeks
    tweeks over 11 years ago
    Andrew Beckett said:

    Oh, and by the way, I always recommend against defining your own "core" functions without prefixes, unless they are in (say) a lexical scope where you can see the definition too. The reason is that for a casual reader, they look like standard functions - and secondly if Cadence then defines a core function which happens to have the same name, your code will break...

    In your example, you used a function foldl1.

    Yes, that code originally lived in a lexical scope (my own personal module system), and I totally forgot it was unprefixed!

    This reminds me of a broader philosophical issue, however.  One feature of Lisp that has gathered much praise over the decades is how functions defined by the programmer look and feel just like functions built into the language.  Without closer inspection, you wouldn't know that fold1 wasn't a SKILL primitive operator.

    I always hear this being described as an advantage, adding to Lisp's flexibility and expressiveness.  However, in systems like Emacs and Virtuoso that lack package/module systems, there is a strong push in the opposite direction, for programmers to name their functions in a conspicuous manner (i.e. with "user" prefixes) so as to avoid inadvertently clashing with builtins!

    I have mixed feelings about this.  In the absense of modules/packages, prefixing makes sense from a maintenance point of view.  However, prefixing destroys that sense of smoothly extending a core language, because SKILL functions all look likeThis(), but my functions have to look CCFlikeThis(), with big ugly capital letters on the front. 

    If I want to add some Common Lisp primitives like "first", "second", "third", etc. to SKILL, I technically ought to name them "CLfirst", "CLsecond", "CLthird", ....   The point is to make SKILL look more like CL, but the effort is largely nullified by putting capital CL at the beginning of everything.  (Emacs has the same problem: cl-first, cl-second...  At least it's lowercase.) 

    I guess there's no point in trying to make SKILL look like another dialect, because such an effort can never be 100% successful without writing a full interpreter.  However, SKILL itself has added gratuitous primitives to its core to make itself look more like Scheme!  For example, eq? is exactly like eq.  Why do we need both of them?  If you're willing to add eq?, why not add zero?, one?, number?, positive?, and procedure? as well?  I sense a half-hearted attempt at Scheme-compatibility.  Everyone knows SKILL++ can never be 100% compatible with Scheme, so why did they even try?  Why flood the namespace with redundant Schemey names for the Maclispy/Common Lispy primitives SKILL inherited from Franz Lisp?  I even made a list of them all:

    boolean? (obj)

    define (g_general g_general \@optional g_general \@rest g_general "ggg")

    eq? (g_general g_general "gg")

    equal? (g_general g_general "gg")

    eqv? (g_general g_general "gg")

    even? (g_general "g")

    for_each (u_function l_list "ul")

    integer? (g_general "g")

    list? (g_general "g")

    negative? (g_general "g")

    null? (g_general "g")

    odd? (g_general "g")

    pair? (g_general "g")

    real? (g_general "g")

    set! (s_symbol g_general "sg")

    set_car (l_list g_general "lg")
    set_cdr (l_list l_list "ll")

    setcar (l_list g_general "lg")
    setcdr (l_list l_list "ll")

    symbol? (g_general "g")

    symbolToString (symbol "s")

    vector? (g_general "g")

    All of these are redundant names.  If you are going to add all the IEEE Scheme names for things, you should at least finish the job!  Will the remaining primitives ever be added?  Why even bother anyway?

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
Children
No Data

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