• 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. Blogs
  2. Analog/Custom Design
  3. SKILL for the Skilled: Sorting With SKILL++
Team SKILL
Team SKILL

Community Member

Blog Activity
Options
  • Subscribe by email
  • More
  • Cancel
CDNS - RequestDemo

Have a question? Need more information?

Contact Us
Team SKILL
programming
functions
sort
Virtuoso
SKILL++
sorting
SKILL

SKILL for the Skilled: Sorting With SKILL++

3 May 2011 • 6 minute read

In the previous couple of SKILL for the Skilled postings we looked at some of the features of SKILL++. In fact, we saw local functions, higher-order functions, and lexical scoping. In this episode of SKILL for the Skilled I would like to show a few more practical examples of these concepts.

Functions are first class

In the SKILL language, functions are themselves first class objects. They can be created dynamically, and they can be passed around as arguments to other functions. We'll see in the examples how to write functions that generate functions, and why you might want to do that.

Review of the SKILL sort function

The SKILL primitive sort function, takes two arguments. The first is the list to be sorted, and the second is a function designator indicating a compare predicate. A predicate is a function whose return value is to be interpreted as TRUE or FALSE. A compliant compare predicate (for sort) promises to accept two arguments and return a boolean value indicating whether the two arguments given are in order in some appropriate sense. Often there is already a built-in SKILL function which does the type of comparison needed, and sometimes an on-the-fly function does the trick. The code in example 5.1 uses a pre-existing function, alphalessp as a compare predicate. In this case, the sort function reorders the list of strings alphabetically.

Sorting with built-in sort predicates

 

;; Example 5.1
(sort (list "this" "is" "a" "list" "of" "words")
'alphalessp)
==> ("a" "is" "list" "of" "this" "words")

As seen previously, if your code is in SKILL++, you can simply reference the global variable whose name is the same as the function name: alphalessp.

 

;; Example 5.2
(inScheme
(sort (list "this" "is" "a" "list" "of" "words")
alphalessp))
==> ("a" "is" "list" "of" "this" "words")

For the rest of this article, please assume all top level SKILL expressions reside in a (inScheme ...) form.

Implementing SKILL++ sort predicates

The compare predicate of sort may actually be any callable object. Several types of objects are callable in SKILL. Symbols such as alphalessp are callable if they name existing functions or are somehow auto-loadable. Function objects created by lambda are also callable.

Global functions get created and named when you use procedure or defun. As we saw previously functions can also be created and named locally using flet and labels. But you can also create nameless functions with lambda.

The code in example 5.3 creates a function named fileLengthLessp.

;; Example 5.3
(defun fileLengthLessp (f1 f2)
(lessp (fileLength f1)
(fileLength f2)))

The code in example 5.4 creates an equivalent function, i.e., a function that does the same thing as fileLengthLessp when called, but which has no name. You have to store the value in a variable or pass the value directly to a function, such as to the sort function.

 

;; Example 5.4
(lambda (f1 f2)
(lessp (fileLength f1)
(fileLength f2)))

In the following examples (5.5, 5.6, and 5.7) we want to sort a list of file names (strings) according to the file size (in bytes). There are several ways to do this. There is a SKILL built-in function to return the file size, but there is no built-in SKILL function which compares file sizes. However Example 5.3 above implements one named fileLengthLessp. We can use that function as an argument to sort.

 

;; Example 5.5
(sort (getDirFiles ".")
fileLengthLessp)
You can also build the function on-the-fly without a name as in Example 5.6.

 

;; Example 5.6
(sort (getDirFiles ".")
(lambda (f1 f2)
(lessp (fileLength f1)
(fileLength f2))))

You can also do this using flet as in example 5.7.

 

;; Example 5.7
(flet ((lesspFileLength (f1 f2)
(lessp (fileLength f1)
(fileLength f2))))
(sort (getDirFiles ".")
lesspFileLength))

 

Reversing the sort order

Two more examples are seen in examples 5.8 and 5.9. Example 5.8 shows how to sort a list of strings in decreasing order according to (string) length; i.e., longest string first.

 

;; Example 5.8
(sort list_of_strings
(lambda (a b)
(greaterp (strlen a)
(strlen b))))
Example 5.9 shows how to sort a list of sub-lists by decreasing order according to (list) length.
;; Example 5.9
(sort list_of_lists
(lambda (a b)
(greaterp (length a)
(length b))))

 

Components of the sort predicate

Notice the similar code structure in examples 5.6, 5.8, and 5.9. There are a couple characteristics of the compare function which we can factor out.

  • test: the kind of relation function, numerical relation such as greater (greaterp) than or less than (lessp), or an alphabetic type of relation such as alphalessp.
  • key: the kind of attribute we want to compare such as length, strlen, fileLength, or identity.
The identity function

It will simplify a few things later if we first define a very simple function called identity to be a unary function which returns its argument. The identity function defined in example 5.10 is to function application, as zero is to addition, and 1 is to numerical multiplication.

;; Example 5.10

(defun identity (x)
x)
Higher order functions -- calculating a sort predicate

We can use SKILL++ to calculate the compare function to pass to sort. Writing functions that generate functions is an easy thing to do in SKILL++.

 

;; Example 5.11
(defun genCmpFunction (@key (test lessp)
(key identity)) ;; see example 5.10
(lambda (A B)
(test (key A)
(key B))))

The function, genCmpFunction defined in Example 5.11, can be called with keyword arguments ?test and ?key and returns a function which is compatible with sort; i.e., it returns a binary function which can be used as a sort predicate. The names test, and key are somewhat standard names--even if a bit confusing. Usage examples are shown in example 5.12. The key defaults to the identity function, and the test defaults to the lessp function.

Using the higher order function

Now, the SKILL sort can be used in a more generalized way. We can rewrite the code examples in 5.5, 5.6, and 5.7.

 

;; Example 5.12

;; reimplementation of example 5.6
;; sort a list of file names by increasing file size
(sort (getDirFiles ".")
(genCmpFunction ?key fileLength))

;; reimplementation of example 5.8
;; sort a list of strings by decreasing string length
(sort list_of_strings
(genCmpFunction ?key strlen
?test greaterp))

;; reimplementation of example 5.9
;; sort a list of sub-lists by decreasing list length
(sort list_of_lists
(genCmpFunction ?key length
?test greaterp))
Reimplementing the sortcar function

Notice that if the built-in function sortcar did not exist in SKILL, we could implement it using sort as shown in example 5.13.

 

;; Example 5.13
(defun sortcar (list predicate)
(sort list
(genCmpFunction ?test predicate
?key car)))

Sorting objects from the Cadence Database

The genCmpFunction can generate useful sort predicates for sorting data base objects under various criteria. Example 5.14 shows how to sort shapes in a Virtuoso layout from top-to-bottom according to top edge.

 

;; Example 5.14
(sort (geGetEditCellView)->shapes
(genCmpFunction ?test greaterp
?key topEdge))
Example 5.15 shows how to sort the db-instances in a schematic alphabetically according to instance name. In this example, we pass ?key as a function which will retrieve value of the name property from a db-instance.

 

;; Example 5.15
(sort (geGetEditCellView)->instances
(genCmpFunction ?test alphalessp
?key (lambda (i) i->name)))

Review

In this posting we looked at the following concepts.

  • The SKILL built-in sort function
  • Sorting list of string alphabetically (examples 5.1, 5.2)
  • Sorting file name by file size (examples 5.5, 5.6, 5.7)
  • Calculating sort predicates programmatically (example 5.11)
  • Reimplementing sortcar based on a generalized sort predicate
  • Using higher-order function in conjunction with sorting strings and db-objects.
To Be Continued

In the next posting we'll see more examples of how to use these types of higher order functions with virtuoso, for example to sort pin figures clockwise around the boundary of the cellView. In addition we'll generalize the genCmpFunction further to allow for secondary and ternary sorting criteria.

Jim Newton

Previous Posts

SKILL for the Skilled: Continued Introduction to SKILL++

SKILL for the Skilled: What is SKILL++?

SKILL for the Skilled: Rule of English Translation

SKILL for the Skilled:  Making Programs Clear and Concise

 


CDNS - RequestDemo

Try Cadence Software for your next design!

Free Trials

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

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