Optional parameters

From Rosetta Code
Revision as of 07:30, 24 May 2009 by rosettacode>Paddy3118 (Python)
Task
Optional parameters
You are encouraged to solve this task according to the task description, using any language you may know.

Define a function/method/subroutine which sorts a sequence ("table") of sequences ("rows") of strings ("cells"), by one of the strings. Besides the input to be sorted, it shall have the following optional parameters:

ordering
A function specifying the ordering of strings; lexicographic by default.
column
An integer specifying which string of each row to compare; the first by default.
reverse
Reverses the ordering.

This task should be considered to include both positional and named optional parameters, as well as overloading on argument count as in Java or selector name as in Smalltalk, or, in the extreme, using different function names. Provide these variations of sorting in whatever way is most natural to your language.

Do not implement a sorting algorithm; this task is about the interface. If you can't use a built-in sort routine, just omit the implementation (with a comment).

Common Lisp

Common Lisp has both named and positional parameters.

<lang lisp> (defun sort-table (table &key (ordering #'string<)

                             (column 0)
                             reverse)
 (sort table (if reverse
                 (complement ordering)
                 ordering)
             :key (lambda (row) (elt row column))))</lang>

(Notes: The builtin sort takes a "less than" predicate function. The complement function inverts a predicate.)

Example uses: <lang lisp>CL-USER> (defparameter *data* '(("a" "b" "c") ("" "q" "z") ("zap" "zip" "Zot")))

  • DATA*

CL-USER> (sort-table *data*) (("" "q" "z") ("a" "b" "c") ("zap" "zip" "Zot"))

CL-USER> (sort-table *data* :column 2) (("zap" "zip" "Zot") ("a" "b" "c") ("" "q" "z"))

CL-USER> (sort-table *data* :column 1) (("a" "b" "c") ("" "q" "z") ("zap" "zip" "Zot"))

CL-USER> (sort-table *data* :column 1 :reverse t) (("zap" "zip" "Zot") ("" "q" "z") ("a" "b" "c"))

CL-USER> (sort-table *data* :ordering (lambda (a b) (> (length a) (length b)))) (("zap" "zip" "Zot") ("a" "b" "c") ("" "q" "z"))</lang>


OCaml

OCaml has optional named parameters.

<lang ocaml>let sort_table ?(ordering = compare) ?(column = 0) ?(reverse = false) table =

 let cmp x y = ordering (List.nth x column) (List.nth y column) * (if reverse then -1 else 1) in
   List.sort cmp table</lang>

Example uses: <lang ocaml># let data = [["a"; "b"; "c"]; [""; "q"; "z"]; ["zap"; "zip"; "Zot"]];; val data : string list list =

 [["a"; "b"; "c"]; [""; "q"; "z"]; ["zap"; "zip"; "Zot"]]
  1. sort_table data;;

- : string list list = [[""; "q"; "z"]; ["a"; "b"; "c"]; ["zap"; "zip"; "Zot"]]

  1. sort_table ~column:2 data;;

- : string list list = [["zap"; "zip"; "Zot"]; ["a"; "b"; "c"]; [""; "q"; "z"]]

  1. sort_table ~column:1 data;;

- : string list list = [["a"; "b"; "c"]; [""; "q"; "z"]; ["zap"; "zip"; "Zot"]]

  1. sort_table ~column:1 ~reverse:true data;;

- : string list list = [["zap"; "zip"; "Zot"]; [""; "q"; "z"]; ["a"; "b"; "c"]]

  1. sort_table ~ordering:(fun a b -> compare (String.length b) (String.length a)) data;;

- : string list list = [["zap"; "zip"; "Zot"]; ["a"; "b"; "c"]; [""; "q"; "z"]]</lang>

Python

Using a pretty-printer for the table <lang python>>>> def printtable(data):

   for row in data:
       print ' '.join('%-5s' % ('"%s"' % cell) for cell in row)


>>> def sorttable(table, ordering=None, column=0, reverse=False):

   return sorted(table, cmp=ordering, key=lambda row: row[column], reverse=reverse)

>>> data = [["a", "b", "c"], ["", "q", "z"], ["zap", "zip", "Zot"]] >>> printtable(data) "a" "b" "c" "" "q" "z" "zap" "zip" "Zot" >>> printtable( sorttable(data) ) "" "q" "z" "a" "b" "c" "zap" "zip" "Zot" >>> printtable( sorttable(data, column=2) ) "zap" "zip" "Zot" "a" "b" "c" "" "q" "z" >>> printtable( sorttable(data, column=1) ) "a" "b" "c" "" "q" "z" "zap" "zip" "Zot" >>> printtable( sorttable(data, column=1, reverse=True) ) "zap" "zip" "Zot" "" "q" "z" "a" "b" "c" >>> printtable( sorttable(data, ordering=lambda a,b: cmp(len(b),len(a))) ) "zap" "zip" "Zot" "a" "b" "c" "" "q" "z" >>> </lang>

Tcl

In Tcl, optional arguments are collected when the last argument to a proc definition is called "args". The lsort command has a similar API, but with different keywords, so we adapt them. <lang Tcl>package require Tcl 8.5

proc tablesort {table args} {

   array set opt {-ordering "" -column 0 -reverse 0}
   array set opt $args
   set pars [list -index $opt(-column)]
   if $opt(-reverse) {lappend pars -decreasing}
   if {$opt(-ordering) ne ""} {lappend pars -command $opt(-ordering)}
   lsort {*}$pars $table

}

% tablesort $data {"" q z} {a b c} {zap zip Zot}

% tablesort $data -column 1 {a b c} {"" q z} {zap zip Zot}

% tablesort $data -column 0 {"" q z} {a b c} {zap zip Zot}

% tablesort $data -column 0 -reverse 1 {zap zip Zot} {a b c} {"" q z}

% tablesort $data -ordering {

       apply {{a b} {expr {[string length $b]-[string length $a]}}}
   }

{zap zip Zot} {a b c} {"" q z} </lang>