module ExampleOptionalParameter
  ! use any module needed for the sort function(s)
  ! and all the interfaces needed to make the code work
  implicit none
contains

  subroutine sort_table(table, ordering, column, reverse)
    type(table_type), intent(inout) :: table
    integer, optional :: column
    logical, optional :: reverse
    optional :: ordering
    interface
       integer function ordering(a, b)
         type(table_element), intent(in) :: a, b
       end function ordering
    end interface

    integer :: the_column, i
    logical :: reversing
    type(table_row) :: rowA, rowB

    if ( present(column) ) then
       if ( column > get_num_of_columns(table) ) then
          ! raise an error?
       else
          the_column = column
       end if
    else
       the_column = 1   ! a default value, de facto
    end if

    reversing = .false.  ! default value
    if ( present(reverse) ) reversing = reverse

    do
       ! loops over the rows to sort... at some point, we need
       ! comparing an element (cell) of the row, with the element
       ! in another row; ... let us suppose rowA and rowB are
       ! the two rows we are considering
       ea = get_element(rowA, the_column)
       eb = get_element(rowB, the_column)
       if ( present(ordering) ) then
          if ( .not. reversing ) then
             if ( ordering(ea, eb) > 0 ) then
                ! swap the rowA with the rowB
             end if
          else   ! < instead of >
             if ( ordering(ea, eb) < 0 ) then
                ! swap the rowA with the rowB
             end if
          end if
       else
          if ( .not. reversing ) then
             if ( lexinternal(ea, eb) > 0 ) then
                ! swap the rowA with the rowB
             end if
          else   ! < instead of >
             if ( lexinternal(ea, eb) < 0 ) then
                ! swap the rowA with the rowB
             end if
          end if
       end if
       ! ... more of the sorting algo ...
       ! ... and rows traversing ... (and an exit condition of course!)
    end do

  end subroutine sort_table

end module ExampleOptionalParameter


Function power(n As Integer, p As Integer = 2) As Double
	Return n ^ p
End Function

Print power(2)       ' muestra 4
Print power(2, 3)    ' muestra 8
Sleep


  title="Rotating Triangle"
  include "OpenglSceneFrame.inc"

  sub Initialize(sys hWnd)
  '=======================
  SetTimer hWnd,1,10,NULL
  end sub
  '
  sub Scene(sys hWnd)
  '==================
  '
  static single ang1,angi1=1
  '
  glClearColor 0.3, 0.3, 0.5, 0
  glClear GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT
  '
  glLoadIdentity
  '
  '
  gltranslatef    0.0, 0.0, -4.0
  glrotatef ang1, 0.0, 0.0,  1.0
  '
  glBegin GL_TRIANGLES
  glColor3f   1.0, 0.0, 0.0 : glVertex3f   0.0,  1.0, 0.0
  glColor3f   0.0, 1.0, 0.0 : glVertex3f  -1.0, -1.0, 0.0
  glColor3f   0.0, 0.0, 1.0 : glVertex3f   1.0, -1.0, 0.0
  glEnd
  '
  'UPDATE ROTATION ANGLES
  '
  ang1+=angi1
  if ang1>360 then ang1-=360
  '
  end sub

  sub Release(sys hwnd)
  '====================
  killTimer hwnd, 1
  end sub


Program OpenGLDemo;

uses
  SysUtils,
  ctypes,
  gl,
  Glut;

procedure paint; cdecl;
begin
  glClearColor(0.3,0.3,0.3,0.0);
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

  glShadeModel(GL_SMOOTH);

  glLoadIdentity();
  glTranslatef(-15.0, -15.0, 0.0);

  glBegin(GL_TRIANGLES);
  glColor3f(1.0, 0.0, 0.0);
  glVertex2f(0.0, 0.0);
  glColor3f(0.0, 1.0, 0.0);
  glVertex2f(30.0, 0.0);
  glColor3f(0.0, 0.0, 1.0);
  glVertex2f(0.0, 30.0);
  glEnd();

  glFlush();
end;

procedure reshape(width, height: cint); cdecl;
begin
  glViewport(0, 0, width, height);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(-30.0, 30.0, -30.0, 30.0, -30.0, 30.0);
  glMatrixMode(GL_MODELVIEW);
end;

begin
  glutInit(@argc, @argv);
  glutInitWindowSize(640, 480);
  glutCreateWindow('Triangle');

  glutDisplayFunc(@paint);
  glutReshapeFunc(@reshape);

  glutMainLoop();
end.


type cell string

type spec struct {
    less     func(cell, cell) bool
    column   int
    reverse  bool
}

func newSpec() (s spec) {
    // initialize any defaults
    return
}

// sort with all defaults
t.sort(newSpec())

// reverse sort
s := newSpec
s.reverse = true
t.sort(s)


def orderedSort(Collection table, column = 0, reverse = false, ordering = {x, y -> x <=> y } as Comparator) {
    table.sort(false) { x, y -> (reverse ? -1 : 1) * ordering.compare(x[column], y[column])}
}


{-# LANGUAGE RecordWildCards #-}

data SorterArgs = SorterArgs { cmp :: String, col :: Int, rev :: Bool } deriving Show
defSortArgs = SorterArgs "lex" 0 False

sorter :: SorterArgs -> [[String]] -> [[String]]
sorter (SorterArgs{..}) = case cmp of
                            _ -> undefined

main = do
    sorter defSortArgs{cmp = "foo", col=1, rev=True} [[]]
    sorter defSortArgs{cmp = "foo"} [[]]
    sorter defSortArgs [[]]
    return ()


use OpenGL;

sub triangle {
    glBegin GL_TRIANGLES;
    glColor3f 1.0, 0.0, 0.0;
    glVertex2f 5.0, 5.0;
    glColor3f 0.0, 1.0, 0.0;
    glVertex2f 25.0, 5.0;
    glColor3f 0.0, 0.0, 1.0;
    glVertex2f 5.0, 25.0;
    glEnd;
};

glpOpenWindow;
glMatrixMode GL_PROJECTION;
glLoadIdentity;
gluOrtho2D 0.0, 30.0, 0.0, 30.0;
glMatrixMode GL_MODELVIEW;

glClear GL_COLOR_BUFFER_BIT;
triangle;
glpFlush;

glpMainLoop;


procedure main()
   X := [ [1,2,3], [2,3,1], [3,1,2])                       # A list of lists
   Sort(X)                                                 # vanilla sort
   Sort(X,"ordering","numeric","column",2,"reverse")       # using optional parameters
end

procedure Sort(X,A[])                                      # A[] provides for a variable number of arguments
   while a := get(A) do {
      case a of {
         "ordering" :  op := case get(A) | runerr(205,a) of {
            "lexicographic"|"string":  "<<"
            "numeric": "<"
            default:  runerr(205,op)
            }
         "column"   : col := 0 < integer(col := get(A)) | runerr(205,col)
         "reverse"  : reverseorder := reverse
         default: runerr(205,a)
         }
   return (\reverseorder|1)(bubblesortf(X,\c|1,\op|"<<"))  # reverse or return the sorted list
end


srtbl=: verb define
  '' srtbl y
:
  '`ordering column reverse'=. x , (#x)}. ]`0:`0:
  |.^:reverse y /: ordering (column {"1 ])y
)


--
-- demo\rosetta\OpenGL.exw
-- =======================
--
with javascript_semantics
requires("1.0.1")
include pGUI.e
include opengl.e

Ihandln dlg
Ihandle canvas

constant fragment_shader = """
precision highp float;
varying vec4 v_color;
void main(void) {
    // "Varying" variables are implicitly interpolated across triangles.
    gl_FragColor = v_color;
}""",
         vertex_shader = """
attribute vec3 a_position;
attribute vec4 a_color;
varying vec4 v_color;
void main(void) {
    gl_Position = vec4(a_position, 1.0);
    v_color = a_color;
}"""

function get_shader(string src, integer stype)
    integer shader = glCreateShader(stype)
    glShaderSource(shader, src)
    glCompileShader(shader)
    if not glGetShaderParameter(shader, GL_COMPILE_STATUS) then
        crash(glGetShaderInfoLog(shader))
    end if
    return shader
end function

constant vertices = { -0.5, -0.5, 0,    -- (bl)
                      +0.5, -0.5, 0,    -- (br)
                      -0.5, +0.5, 0 },  -- (tl)
--                    +0.5, +0.5, 0 },  -- (tr)
         colours = { 1, 0, 0, 1,    -- red (bl)
                     0, 1, 0, 1,    -- green (br)
                     0, 0, 1, 1 }   -- blue (tl)

procedure set_shader()
    IupGLMakeCurrent(canvas)
    integer shaderProgram = glCreateProgram()
    glAttachShader(shaderProgram, get_shader(vertex_shader,GL_VERTEX_SHADER))
    glAttachShader(shaderProgram, get_shader(fragment_shader,GL_FRAGMENT_SHADER))
    glLinkProgram(shaderProgram)
    if not glGetProgramParameter(shaderProgram, GL_LINK_STATUS) then
        crash(glGetProgramInfoLog(shaderProgram))
    end if
    glUseProgram(shaderProgram)
    // Get the indexes to communicate vertex attributes to the program.
    integer positionAttr = glGetAttribLocation(shaderProgram, "a_position"),
            colorAttr = glGetAttribLocation(shaderProgram, "a_color")

    // And specify that we will be actually delivering data to those attributes.
    glEnableVertexAttribArray(positionAttr)
    glEnableVertexAttribArray(colorAttr)

    // Store vertex positions and colors in array buffer objects.
    integer positionBuffer = glCreateBuffer()
    glBindBuffer(GL_ARRAY_BUFFER, positionBuffer)
    {integer size, atom pData} = glFloat32Array(vertices)
    glBufferData(GL_ARRAY_BUFFER, size, pData, GL_STATIC_DRAW)
    glEnableVertexAttribArray(positionBuffer)
    integer colorBuffer = glCreateBuffer()
    glBindBuffer(GL_ARRAY_BUFFER, colorBuffer)
    {size, pData} = glFloat32Array(colours)
    glBufferData(GL_ARRAY_BUFFER, size, pData, GL_STATIC_DRAW)
    glEnableVertexAttribArray(colorBuffer)
    glEnable(GL_DEPTH_TEST)
    //   Specify the array data to render.
    //   3 and 4 are the lengths of the vectors (3 for XYZ, 4 for RGBA).
    glBindBuffer(GL_ARRAY_BUFFER, positionBuffer)
    glVertexAttribPointer(positionAttr, 3, GL_FLOAT, false, 0, 0)
    glEnableVertexAttribArray(positionAttr)
    glBindBuffer(GL_ARRAY_BUFFER, colorBuffer)
    glVertexAttribPointer(colorAttr, 4, GL_FLOAT, false, 0, 0)
    glEnableVertexAttribArray(colorAttr)
end procedure

bool drawn = false

function action(Ihandle /*ih*/)
    if not drawn or platform()!=JS then
        glClearColor(0.3, 0.3, 0.3, 1.0)
        integer {w,h} = IupGetIntInt(canvas,"DRAWSIZE")
        glViewport(0, 0, w, h)
        glClear(GL_COLOR_BUFFER_BIT || GL_DEPTH_BUFFER_BIT)

        // Draw triangles using the specified arrays.
        integer numVertices = length(vertices)/3  // 3 coordinates per vertex
        glDrawArrays(GL_TRIANGLES, 0, numVertices)

        // Check for errors.
        while true do
            integer e = glGetError()
            if e=GL_NO_ERROR then exit end if
            printf(1,"GL error %d\n", e)
        end while

        glFlush()
        drawn = true
    end if
    return IUP_DEFAULT
end function

procedure main()
    IupOpen()
    canvas = IupGLCanvas(Icallback("action"), "RASTERSIZE=640x480")
    dlg = IupDialog(canvas, "TITLE=OpenGLShader, SHRINK=YES")
    IupMap(dlg)
    set_shader()
    IupShow(dlg)
    if platform()!=JS then
        IupMainLoop()
        dlg = IupDestroy(dlg)
        IupClose()
    end if
end procedure
main()


import java.util.*;

public class OptionalParams {
    // "natural ordering" comparator
    static <T extends Comparable<? super T>> Comparator<T> naturalOrdering() {
        return Collections.reverseOrder(Collections.<T>reverseOrder());
    }

    public static <T extends Comparable<? super T>> void
                             sortTable(T[][] table) {
        sortTable(table, 0);
    }
    public static <T extends Comparable<? super T>> void
                             sortTable(T[][] table,
                                       int column) {
        sortTable(table, column, false);
    }
    public static <T extends Comparable<? super T>> void
                             sortTable(T[][] table,
                                       int column, boolean reverse) {
        sortTable(table, column, reverse, OptionalParams.<T>naturalOrdering());
    }
    public static <T> void sortTable(T[][] table,
                                     final int column,
                                     final boolean reverse,
                                     final Comparator<T> ordering) {
        Comparator<T[]> myCmp = new Comparator<T[]>() {
            public int compare(T[] x, T[] y) {
                return (reverse ? -1 : 1) *
                       ordering.compare(x[column], y[column]);
            }
        };
        Arrays.sort(table, myCmp);
    }

    public static void main(String[] args) {
        String[][] data0 = {{"a", "b", "c"},
                            {"", "q", "z"},
                            {"zap", "zip", "Zot"}};
        System.out.println(Arrays.deepToString(data0));
        // prints: [[a, b, c], [, q, z], [zap, zip, Zot]]

        // we copy it so that we don't change the original copy
        String[][] data = data0.clone();
        sortTable(data);
        System.out.println(Arrays.deepToString(data));
        // prints: [[, q, z], [a, b, c], [zap, zip, Zot]]

        data = data0.clone();
        sortTable(data, 2);
        System.out.println(Arrays.deepToString(data));
        // prints: [[zap, zip, Zot], [a, b, c], [, q, z]]

        data = data0.clone();
        sortTable(data, 1);
        System.out.println(Arrays.deepToString(data));
        // prints: [[a, b, c], [, q, z], [zap, zip, Zot]]

        data = data0.clone();
        sortTable(data, 1, true);
        System.out.println(Arrays.deepToString(data));
        // prints: [[zap, zip, Zot], [, q, z], [a, b, c]]

        data = data0.clone();
        sortTable(data, 0, false, new Comparator<String>() {
                public int compare(String a, String b) {
                    return b.length() - a.length();
                }
            });
        System.out.println(Arrays.deepToString(data));
        // prints: [[zap, zip, Zot], [a, b, c], [, q, z]]
    }
}


(load "@lib/openGl.l")

(glutInit)
(glutInitWindowSize 400 300)
(glutCreateWindow "Triangle")

(displayPrg
   (glClearColor 0.3 0.3 0.3 0.0)
   (glClear (| GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT))
   (glShadeModel GL_SMOOTH)
   (glLoadIdentity)
   (glTranslatef -15.0 -15.0 0.0)
   (glBegin GL_TRIANGLES)
   (glColor3f 1.0 0.0 0.0)
   (glVertex2f 0.0 0.0)
   (glColor3f 0.0 1.0 0.0)
   (glVertex2f 30.0 0.0)
   (glColor3f 0.0 0.0 1.0)
   (glVertex2f 0.0 30.0)
   (glEnd)
   (glFlush) )

(reshapeFunc
   '((Width Height)
      (glViewport 0 0 Width Height)
      (glMatrixMode GL_PROJECTION)
      (glLoadIdentity)
      (glOrtho -30.0 30.0 -30.0 30.0 -30.0 30.0)
      (glMatrixMode GL_MODELVIEW) ) )

# Exit upon mouse click
(mouseFunc '((Btn State X Y) (bye)))

(glutMainLoop)


int main() {
	GLUE.init(([
		"fullscreen": 0,
		"resolution": ({ 640, 480 }),
	]));

	while (1) {
		GL.glViewport(0, 0, 640, 480);
		GL.glMatrixMode(GL.GL_PROJECTION);
		GL.glLoadIdentity();
		GL.glOrtho(-30.0, 30.0, -30.0, 30.0, -30.0, 30.0);
		GL.glMatrixMode(GL.GL_MODELVIEW);

		GL.glClearColor(0.3,0.3,0.3,0.0);
		GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

		GL.glShadeModel(GL.GL_SMOOTH);

		GL.glLoadIdentity();
		GL.glTranslate(-15.0, -15.0, 0.0);

		GL.glBegin(GL.GL_TRIANGLES);
		GL.glColor(1.0, 0.0, 0.0);
		GL.glVertex(0.0, 0.0);
		GL.glColor(0.0, 1.0, 0.0);
		GL.glVertex(30.0, 0.0);
		GL.glColor(0.0, 0.0, 1.0);
		GL.glVertex(0.0, 30.0);
		GL.glEnd();

		GL.glFlush();

		GLUE.swap_buffers();
		Pike.DefaultBackend(0.0);
		sleep(0.01);
	}
}


function sorter(table, options) {
    opts = {}
    opts.ordering = options.ordering || 'lexicographic';
    opts.column   = options.column || 0;
    opts.reverse  = options.reverse || false;

    // ...
}

sorter(the_data, {reverse: true, ordering: 'numeric'});


sorttable(T; ordering=<, column=1, reverse=false) =
  sort(T, by = t -> t[column], lt = reverse ? (a,b) -> ordering(b,a) : ordering)
sorttable(T, ordering=<, column=1, reverse=false) =
  sorttable(T, ordering=ordering, column=column, reverse=reverse)


include ..\Utilitys.tlhy

:mypower
    1 tolist flatten len
    1 equal
    ( [pop drop 2]
      [pop pop drop]
    ) if
    power
;

"2 ^2 = " print 2 mypower ?
"2 ^3 = " print ( 2 3 ) mypower ?

"End " input


XIncludeFile "OpenGL.pbi"
pfd.PIXELFORMATDESCRIPTOR
FlatMode = 0 ; Enable Or disable the 'Flat' rendering
WindowWidth = 800 ; The window & GLViewport dimensions
WindowHeight = 600
hWnd = OpenWindow(0, 0, 0, WindowWidth, WindowHeight, "OpenGL Triangle", #PB_Window_SystemMenu)
hdc = GetDC_(hWnd)
pfd\nSize = SizeOf(PIXELFORMATDESCRIPTOR)
pfd\nVersion = 1
pfd\dwFlags = #PFD_SUPPORT_OPENGL | #PFD_DOUBLEBUFFER | #PFD_DRAW_TO_WINDOW
pfd\dwLayerMask = #PFD_MAIN_PLANE
pfd\iPixelType = #PFD_TYPE_RGBA
pfd\cColorBits = 24
pfd\cDepthBits = 16
pixformat = ChoosePixelFormat_(hdc, pfd)
SetPixelFormat_(hdc, pixformat, pfd)
hrc = wglCreateContext_(hdc)
wglMakeCurrent_(hdc,hrc)
glViewport_ (0, 0, WindowWidth-30, WindowHeight-30)
glPushMatrix_()
glMatrixMode_(#GL_MODELVIEW)
glBegin_(#GL_TRIANGLES );
glColor3f_(1.0, 0.0, 0.0 )
glVertex2f_( 0.0, 1.0 )
glColor3f_( 0.0, 1.0, 0.0 )
glVertex2f_( 0.87, -0.5 );
glColor3f_( 0.0, 0.0, 1.0 )
glVertex2f_( -0.87, -0.5 );
glEnd_()
glPopMatrix_()
glFinish_()
SwapBuffers_(hdc)
While Quit = 0
  Repeat
    EventID = WindowEvent()
    Select EventID
    Case #PB_Event_CloseWindow
      Quit = 1
    EndSelect
  Until EventID = 0
Wend


#!/usr/bin/env python
#-*- coding: utf-8 -*-

from OpenGL.GL import *
from OpenGL.GLUT import *

def paint():
    glClearColor(0.3,0.3,0.3,0.0)
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)

    glShadeModel(GL_SMOOTH)

    glLoadIdentity()
    glTranslatef(-15.0, -15.0, 0.0)

    glBegin(GL_TRIANGLES)
    glColor3f(1.0, 0.0, 0.0)
    glVertex2f(0.0, 0.0)
    glColor3f(0.0, 1.0, 0.0)
    glVertex2f(30.0, 0.0)
    glColor3f(0.0, 0.0, 1.0)
    glVertex2f(0.0, 30.0)
    glEnd()

    glFlush()

def reshape(width, height):
    glViewport(0, 0, width, height)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glOrtho(-30.0, 30.0, -30.0, 30.0, -30.0, 30.0)
    glMatrixMode(GL_MODELVIEW)

if __name__ == '__main__':
    glutInit(1, 1)
    glutInitWindowSize(640, 480)
    glutCreateWindow("Triangle")

    glutDisplayFunc(paint)
    glutReshapeFunc(reshape)

    glutMainLoop()


// version 1.1.51

typealias Table = List<List<String>>

/* Note that if ordering is specified, first two parameters are ignored */
fun Table.sort(
    column: Int = 0,
    reverse: Boolean = false,
    ordering: Comparator<List<String>> =
        if (!reverse) compareBy  { it[column] }
        else compareByDescending { it[column] }
) = this.sortedWith(ordering)

fun Table.print(title: String) {
    println(title)
    for (i in 0 until this.size) {
        for (j in 0 until this[0].size) System.out.print("%-3s  ".format(this[i][j]))
        println()
    }
    println()
}

fun main(args: Array<String>) {
    val table = listOf(
        listOf("a", "b", "c"),
        listOf("", "q", "z"),
        listOf("zap", "zip", "Zot")
    )
    table.print("Original:")

    val titles = listOf(
        "Sorted by col 0:", "Sorted by col 1:", "Sorted by col 2:",
        "Reverse sorted by col 0:", "Reverse sorted by col 1:", "Reverse Sorted by col 2"
    )
    val params = listOf(
        0 to false, 1 to false, 2 to false, 0 to true, 1 to true, 2 to true
    )
    for ((i, title) in titles.withIndex()) {
        val table2 = table.sort(params[i].first, params[i].second)
        table2.print(title)
    }
    // using non-default Comparator (case insensitive by col 2, reversed)
    val comp: Comparator<List<String>> = compareByDescending { it[2].toLowerCase() }
    val table3 = table.sort(ordering = comp)
    table3.print("Reverse case insensitive sort by col 2:")
}


define sortarray( // params are set by position
	items::array, // required param
	ordering::string	= 'lexicographic', // optional param
	column::integer		= 1,
	reverse::boolean	= false
) => {
	// sorting process
	local(sorteditems = array)
	// Lasso has no build in method to sort an array of arrays by position in the contained arrays
	// But a method could be built for it
	return #sorteditems
}

define sortarray(
	-items::array, // required param
	-ordering::string	= 'lexicographic', // optional param
	-column::integer	= 1,
	-reverse::boolean	= false
) => sortarray(#items, #ordering, #column, #reverse)

local(items = array(
	array(10, 'red', 'Volvo'),
	array(15, 'gren', 'Ford'),
	array(48, 'yellow', 'Kia'),
	array(12, 'black', 'Holden'),
	array(19, 'brown', 'Fiat'),
	array(8, 'pink', 'Batmobile'),
	array(74, 'orange', 'Bicycle')
))

sortarray(-items = #items, -reverse)

sortarray(#items)


'Task
'Display a smooth shaded triangle with OpenGL.
Screen _NewImage(600, 600, 32)
Dim Shared glInit As Integer
glInput = 0
Do While InKey$ = "": Loop
End

Sub _GL ()
    If glInit = 0 Then
        _glViewport 1, 1, 600, 600
        _glClearColor 0, 0, 0, 1
        glInit = -1
    End If
    _glClear _GL_COLOR_BUFFER_BIT
    _glBegin _GL_TRIANGLES
    _glColor4f 1, 0, 0, 1
    _glVertex2f -1, -1
    _glColor4f 0, 1, 0, 1
    _glVertex2f 0, 0
    _glColor4f 0, 0, 1, 1
    _glVertex2f 1, -1
    _glEnd
End Sub


library(rgl)
x <- c(-1, -1, 1)
y <- c(0, -1, -1)
z <- c(0, 0, 0)
M <- cbind(x,y,z)
rgl.bg(color="gray15")
triangles3d(M, col=rainbow(8))


#lang racket/gui
(require sgl/gl)

(define (resize w h)
  (glViewport 0 0 w h))

(define (draw-opengl)
  (glClearColor 0.0 0.0 0.0 0.0)
  (glClear GL_COLOR_BUFFER_BIT)

  (glShadeModel GL_SMOOTH)

  (glMatrixMode GL_PROJECTION)
  (glLoadIdentity)
  (glOrtho 0.0 1.0 0.0 1.0 -1.0 1.0)
  (glMatrixMode GL_MODELVIEW)
  (glLoadIdentity)

  (glBegin GL_TRIANGLES)
  (glColor3f 1 0 0)
  (glVertex3d 0.25 0.25 0.0)
  (glColor3f 0 1 0)
  (glVertex3d 0.75 0.25 0.0)
  (glColor3f 0 0 1)
  (glVertex3d 0.75 0.75 0.0)
  (glEnd))

(define my-canvas%
  (class* canvas% ()
    (inherit with-gl-context swap-gl-buffers)
    (define/override (on-paint)
      (with-gl-context (λ() (draw-opengl) (swap-gl-buffers))))
    (define/override (on-size width height)
      (with-gl-context (λ() (resize width height) (on-paint))))
    (super-instantiate () (style '(gl)))))

(define win (new frame% [label "Racket Rosetta Code OpenGL example"]
                        [min-width 200] [min-height 200]))
(define gl  (new my-canvas% [parent win]))

(send win show #t)


use NativeCall;

class Window is repr('CPointer') {}
class Monitor is repr('CPointer') {}

# GLFW

constant $lib = ('glfw', v3);

sub glfwInit(--> int32) is native($lib) {*}
sub glfwCreateWindow(int32, int32, Str, Monitor, Window --> Window) is native($lib) {*}
sub glfwTerminate() is native($lib) {*}
sub glfwMakeContextCurrent(Window) is native($lib) {*}
sub glfwSetWindowShouldClose(Window, int32) is native($lib) {*}
sub glfwWindowShouldClose(Window --> int32) is native($lib) {*}
sub glfwSwapBuffers(Window) is native($lib) {*}
sub glfwSwapInterval(int32) is native($lib) {*}
sub glfwPollEvents() is native($lib) {*}
sub glfwGetFramebufferSize(Window, int32 is rw, int32 is rw) is native($lib) {*}

# OpenGL

enum PrimitiveMode(
  GL_TRIANGLES =>	0x0004,
);

enum MatrixMode(
  GL_MATRIX_MODE => 0x0BA0,
  GL_MODELVIEW => 0x1700,
  GL_PROJECTION => 0x1701,
);

constant $gllib = 'GL';

sub glViewport(int32, int32, int32, int32) is native($gllib) {*}
sub glClear(int32) is native($gllib) {*}
sub glMatrixMode(int32) is native($gllib) {*}
sub glLoadIdentity() is native($gllib) {*}
sub glOrtho(num64, num64, num64, num64, num64, num64) is native($gllib) {*}
sub glRotatef(num32, num32, num32, num32) is native($gllib) {*}
sub glBegin(int32) is native($gllib) {*}
sub glColor3f(num32, num32, num32) is native($gllib) {*}
sub glVertex3f(num32, num32, num32) is native($gllib) {*}
sub glEnd() is native($gllib) {*}

constant GL_COLOR_BUFFER_BIT = 0x00004000;

die 'Failed to initialize GLFW' unless glfwInit().so;

my $w = glfwCreateWindow(640, 480, "OpenGL Triangle", Nil, Nil);
without $w { glfwTerminate(); die 'Failed to create window' }

glfwMakeContextCurrent($w);
glfwSwapInterval(1);

while not glfwWindowShouldClose($w) {
    my num32 $ratio;
    my int32 $width;
    my int32 $height;

    glfwGetFramebufferSize($w, $width, $height);
    $ratio = ($width / $height).Num;

    glViewport(0, 0, $width, $height);
    glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-$ratio, $ratio, -1e0, 1e0, 1e0, -1e0);
    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();
    glRotatef((now % 360 * 100e0) , 0e0, 0e0,  1e0);

    glBegin(GL_TRIANGLES);
    glColor3f(1e0, 0e0, 0e0);
    glVertex3f(5e-1, -2.88e-1, 0e0);
    glColor3f(0e0, 1e0, 0e0);
    glVertex3f(-5e-1, -2.88e-1, 0e0);
    glColor3f(0e0, 0e0, 1e0);
    glVertex3f( 0e0, 5.73e-1, 0e0);
    glEnd();

    glfwSwapBuffers($w);
    glfwPollEvents();
}

glfwTerminate();


to sort :table [:column 1] [:ordering "before?] [:reverse "false]
  ; ...
end


function showTable(tbl)
	if type(tbl)=='table' then
		local result = {}
		for _, val in pairs(tbl) do
			table.insert(result, showTable(val))
		end
		return '{' .. table.concat(result, ', ') .. '}'
	else
		return (tostring(tbl))
	end
end

function sortTable(op)
	local tbl = op.table or {}
	local column = op.column or 1
	local reverse = op.reverse or false
	local cmp = op.cmp or (function (a, b) return a < b end)
	local compareTables = function (a, b)
		local result = cmp(a[column], b[column])
		if reverse then return not result else return result end
	end
	table.sort(tbl, compareTables)
end

A = {{"quail", "deer", "snake"},
	{"dalmation", "bear", "fox"},
	{"ant", "cougar", "coyote"}}
print('original', showTable(A))

sortTable{table=A}
print('defaults', showTable(A))

sortTable{table=A, column=2}
print('col 2    ', showTable(A))

sortTable{table=A, column=3}
print('col 3    ', showTable(A))

sortTable{table=A, column=3, reverse=true}
print('col 3 rev', showTable(A))

sortTable{table=A, cmp=(function (a, b) return #a < #b end)}
print('by length', showTable(A))


# Project: OpenGL

load "freeglut.ring"
load "opengl21lib.ring"

func main
        glutInit()
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
        glutInitWindowSize(320,320)
        glutInitWindowPosition(100, 10)
        glutCreateWindow("OpenGL")
        glutDisplayFunc(:renderScene)
        glutMainLoop()

func renderScene
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glBegin(GL_TRIANGLES)
                glVertex3f(-0.5,-0.5,0.0)
                glVertex3f(0.5,0.0,0.0)
                glVertex3f(0.0,0.5,0.0)
        glEnd()
        glutSwapBuffers()


require 'rubygems'
require 'gl'
require 'glut'

include Gl
include Glut

paint = lambda do
  glClearColor(0.3,0.3,0.3,0.0)
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

  glShadeModel(GL_SMOOTH)

  glLoadIdentity
  glTranslatef(-15.0, -15.0, 0.0)

  glBegin(GL_TRIANGLES)
    glColor3f(1.0, 0.0, 0.0)
    glVertex2f(0.0, 0.0)
    glColor3f(0.0, 1.0, 0.0)
    glVertex2f(30.0, 0.0)
    glColor3f(0.0, 0.0, 1.0)
    glVertex2f(0.0, 30.0)
  glEnd

  glFlush
end

reshape = lambda do |width, height|
  glViewport(0, 0, width, height)
  glMatrixMode(GL_PROJECTION)
  glLoadIdentity
  glOrtho(-30.0, 30.0, -30.0, 30.0, -30.0, 30.0)
  glMatrixMode(GL_MODELVIEW)
end

glutInit
glutInitWindowSize(640, 480)
glutCreateWindow("Triangle")

glutDisplayFunc(paint)
glutReshapeFunc(reshape)

glutMainLoop


use glow::*;
use glutin::event::*;
use glutin::event_loop::{ControlFlow, EventLoop};
use std::os::raw::c_uint;

const VERTEX: &str = "#version 410
const vec2 verts[3] = vec2[3](
    vec2(0.5f, 1.0f),
    vec2(0.0f, 0.0f),
    vec2(1.0f, 0.0f)
);
out vec2 vert;
void main() {
    vert = verts[gl_VertexID];
    gl_Position = vec4(vert - 0.5, 0.0, 1.0);
}";

const FRAGMENT: &str = "#version 410
precision mediump float;
in vec2 vert;
out vec4 color;
void main() {
    color = vec4(vert, 0.5, 1.0);
}";

unsafe fn create_program(gl: &Context, vert: &str, frag: &str) -> c_uint {
    let program = gl.create_program().expect("Cannot create program");
    let shader_sources = [(glow::VERTEX_SHADER, vert), (glow::FRAGMENT_SHADER, frag)];

    let mut shaders = Vec::new();
    for (shader_type, shader_source) in shader_sources.iter() {
        let shader = gl
            .create_shader(*shader_type)
            .expect("Cannot create shader");
        gl.shader_source(shader, shader_source);
        gl.compile_shader(shader);
        if !gl.get_shader_compile_status(shader) {
            panic!(gl.get_shader_info_log(shader));
        }
        gl.attach_shader(program, shader);
        shaders.push(shader);
    }

    gl.link_program(program);
    if !gl.get_program_link_status(program) {
        panic!(gl.get_program_info_log(program));
    }

    for shader in shaders {
        gl.detach_shader(program, shader);
        gl.delete_shader(shader);
    }
    program
}

fn main() {
    let (gl, event_loop, window) = unsafe {
        let el = EventLoop::new();
        let wb = glutin::window::WindowBuilder::new()
            .with_title("Hello triangle!")
            .with_inner_size(glutin::dpi::LogicalSize::new(1024.0, 768.0));
        let windowed_context = glutin::ContextBuilder::new()
            .with_vsync(true)
            .build_windowed(wb, &el)
            .unwrap();
        let windowed_context = windowed_context.make_current().unwrap();
        let context = glow::Context::from_loader_function(|s| {
            windowed_context.get_proc_address(s) as *const _
        });
        (context, el, windowed_context)
    };

    let (program, vab) = unsafe {
        let vertex_array = gl
            .create_vertex_array()
            .expect("Cannot create vertex array");
        gl.bind_vertex_array(Some(vertex_array));

        let program = create_program(&gl, VERTEX, FRAGMENT);
        gl.use_program(Some(program));

        (program, vertex_array)
    };

    event_loop.run(move |ev, _, flow| match ev {
        Event::WindowEvent {
            event: WindowEvent::CloseRequested, ..
        } => {
            unsafe {
                gl.delete_program(program);
                gl.delete_vertex_array(vab);
            }
            *flow = ControlFlow::Exit;
        }
        Event::WindowEvent {
            event: WindowEvent::Resized(size), ..
        } => {
            unsafe {
                gl.viewport(0, 0, size.width as i32, size.height as i32);
            }
            window.resize(size);
        }
        Event::RedrawRequested(_) => unsafe {
            gl.clear_color(0.1, 0.2, 0.3, 1.0);
            gl.clear(glow::COLOR_BUFFER_BIT);
            gl.draw_arrays(glow::TRIANGLES, 0, 3);
            window.swap_buffers().unwrap();
        },
        _ => {}
    });
}


OptionalSort := proc(input, {
    ordering :: Or(procedures,identical("lexicographic")) := "lexicographic",
    column :: posint := 1,
    reverse :: truefalse := false
} )
    local compare;
    if ordering = "lexicographic" then
        compare := (x,y)->evalb(`if`(reverse,x[column]>=y[column],x[column]<=y[column]));
    else
    	compare := (x,y)->`if`(reverse,ordering(x[column],y),ordering(y,x));
    end if;
    sort( input, compare );
end proc:


Options[OptionalSort]={ordering->lexicographic,column->1,reverse-> False};
OptionalSort[x_List,OptionsPattern[]]:=If[OptionValue[reverse]==True,
SortBy[x ,#[[OptionValue[column]]]&]//Reverse,
SortBy[x,#[[OptionValue[column]]]&] ]

OptionalSort[{{"a" ,"b", "c"}, {"", "q", "z"},{"zap" ,"zip", "Zot"}} ]
->{{,q,z},{a,b,c},{zap,zip,Zot}}

OptionalSort[{{"a" ,"b", "c"}, {"", "q", "z"},{"zap" ,"zip", "Zot"}},{ordering->lexicographic,column->2,reverse-> True} ]
->{{zap,zip,Zot},{,q,z},{a,b,c}}


Sorter (table : list[list[string]], ordering = "lexicographic", column = 0, reverse = false) : list[list[string]]
{
    // implementation goes here
}


import algorithm, strutils, sugar

proc printTable(a: seq[seq[string]]) =
  for row in a:
    for x in row: stdout.write x, repeat(' ', 4 - x.len)
    echo ""
  echo ""

proc sortTable(a: seq[seq[string]], column = 0, reverse = false,
    ordering: (proc(a,b: string): int) = system.cmp) : seq[seq[string]] =
  let order = if reverse: Descending else: Ascending
  result = a
  result.sort(proc(x,y:seq[string]):int = ordering(x[column],y[column]), order)

const data = @[@["a", "b", "c"], @["", "q", "z"], @["zap", "zip", "Zot"]]

printTable data
printTable sortTable(data)
printTable sortTable(data, column = 2)
printTable sortTable(data, column = 1)
printTable sortTable(data, column = 1, reverse = true)
printTable sortTable(data, ordering = (a,b) => cmp[int](b.len,a.len))


typedef enum { kOrdNone, kOrdLex, kOrdByAddress, kOrdNumeric } SortOrder;

@interface MyArray : NSObject {}
// . . .
@end

@implementation MyArray

- (void)sort {
    [self sortWithOrdering:kOrdLex onColumn:0 reversed:NO];
}

- (void)sortWithOrdering:(SortOrder)ord {
    [self sortWithOrdering:ord onColumn:0 reversed:NO];
}

- (void)sortWithOrdering:(SortOrder)ord onColumn:(int)col {
    [self sortWithOrdering:ord onColumn:col reversed:NO];
}

- (void)sortWithOrdering:(SortOrder)ord onColumn:(int)col reversed:(BOOL)rev {
    // . . . Actual sort goes here . . .
}

@end


import org.lwjgl.opengl.{ Display, DisplayMode }
import org.lwjgl.opengl.GL11._

object OpenGlExample extends App {

  def render() {

    glClearColor(0.3f, 0.3f, 0.3f, 0.0f)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

    glShadeModel(GL_SMOOTH)

    glLoadIdentity()
    glTranslatef(-15.0f, -15.0f, 0.0f)

    glBegin(GL_TRIANGLES)
    glColor3f(1.0f, 0.0f, 0.0f)
    glVertex2f(0.0f, 0.0f)
    glColor3f(0.0f, 1.0f, 0.0f)
    glVertex2f(30f, 0.0f)
    glColor3f(0.0f, 0.0f, 1.0f)
    glVertex2f(0.0f, 30.0f)
    glEnd()
  }

  Display.setDisplayMode(new DisplayMode(640, 480))
  Display.create()

  glMatrixMode(GL_PROJECTION)
  glLoadIdentity()
  glOrtho(-30, 30, -30, 30, -30, 30)
  glMatrixMode(GL_MODELVIEW)

  while (!Display.isCloseRequested()) {
    render()
    Display.update()
    Thread.sleep(1000)
  }
}


package require Tk
package require tcl3d

proc resizedWin {win w h} {
    glViewport 0 0 $w $h
    glMatrixMode GL_PROJECTION
    glLoadIdentity
    glOrtho -30.0 30.0 -30.0 30.0 -30.0 30.0
    glMatrixMode GL_MODELVIEW
}
proc paintShape {win} {
    glClearColor 0.0 0.0 0.0 0.5
    glClear [expr {$::GL_COLOR_BUFFER_BIT+$::GL_DEPTH_BUFFER_BIT}]
    glShadeModel GL_SMOOTH
    glLoadIdentity
    glTranslatef -15.0 -15.0 0.0
    glBegin GL_TRIANGLES
    glColor3f 1.0 0.0 0.0
    glVertex2f 5.0 5.0
    glColor3f 0.0 1.0 0.0
    glVertex2f 25.0 5.0
    glColor3f 0.0 0.0 1.0
    glVertex2f 5.0 25.0
    glEnd
    $win swapbuffers
}

togl .surface -width 640 -height 480 -double true -depth true \
    -displayproc paintShape -reshapeproc resizedWin
pack .surface -fill both -expand 1


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


declare
  class Table
     attr
        rows

     meth init(Rows)
        rows := Rows
     end

     meth sort(ordering:O<=Lexicographic  column:C<=1  reverse:R<=false)
        fun {Predicate Row1 Row2}
           Res = {O {Nth Row1 C} {Nth Row2 C}}
        in
           if R then {Not Res} else Res end
        end
     in
        rows := {Sort @rows Predicate}
     end
  end

  fun {Lexicographic As Bs}  %% omitted for brevity
  end

  T = {New Table init([["a" "b" "c"] ["" "q" "z"] ["zap" "zip" "Zot"]])}
in
  {T sort}
  {T sort(column:3)}
  {T sort(column:2)}
  {T sort(column:2 reverse:true)}
  {T sort(ordering:fun {$ A B} {Length B} < {Length A} end)}


/* opengl.wren */

var GL_COLOR_BUFFER_BIT = 0x4000
var GL_DEPTH_BUFFER_BIT = 0x0100

var GL_SMOOTH = 0x1d01
var GL_MODELVIEW = 0x1700
var GL_PROJECTION = 0x1701

var GL_TRIANGLES = 0x0004

var GLUT_ACTION_ON_WINDOW_CLOSE = 0x01f9
var GLUT_ACTION_GLUTMAINLOOP_RETURNS = 0x0001

class GL {
    foreign static clearColor(red, green, blue, alpha)

    foreign static clear(mask)

    foreign static shadeModel(mode)

    foreign static loadIdentity()

    foreign static translatef(x, y, z)

    foreign static begin(mode)

    foreign static color3f(red, green, blue)

    foreign static vertex2f(x, y)

    foreign static end()

    foreign static flush()

    foreign static viewport(x, y, width, height)

    foreign static matrixMode(mode)

    foreign static ortho(left, right, bottom, top, nearVal, farVal)
}

class Glut {
    foreign static initWindowSize(width, height)

    foreign static createWindow(name)

    foreign static displayFunc(clazz, signature)

    foreign static reshapeFunc(clazz, signature)

    foreign static setOption(eWhat, value)
}

class GLCallbacks {
    static paint() {
        GL.clearColor(0.3, 0.3, 0.3, 0)
        GL.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        GL.shadeModel(GL_SMOOTH)
        GL.loadIdentity()
        GL.translatef(-15, -15, 0)
        GL.begin(GL_TRIANGLES)
        GL.color3f(1, 0, 0)
        GL.vertex2f(0, 0)
        GL.color3f(0, 1, 0)
        GL.vertex2f(30, 0)
        GL.color3f(0, 0, 1)
        GL.vertex2f(0, 30)
        GL.end()
        GL.flush()
    }

    static reshape(width, height) {
        GL.viewport(0, 0, width, height)
        GL.matrixMode(GL_PROJECTION)
        GL.loadIdentity()
        GL.ortho(-30, 30, -30, 30, -30, 30)
        GL.matrixMode(GL_MODELVIEW)
    }
}

Glut.initWindowSize(640, 480)
Glut.createWindow("Triangle")
Glut.displayFunc("GLCallbacks", "paint()")
Glut.reshapeFunc("GLCallbacks", "reshape(_,_)")
Glut.setOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS)


sort(v, ordering=0, column=0, reverse=0)


sub sorttable
 {my @table = @{shift()};
  my %opt =
     (ordering => sub {$_[0] cmp $_[1]}, column => 0, reverse => 0, @_);
  my $col = $opt{column};
  my $func = $opt{ordering};
  my @result = sort
      {$func->($a->[$col], $b->[$col])}
      @table;
  return ($opt{reverse} ? [reverse @result] : \@result);}


function increment(integer i, inc=1)
    return i+inc
end function

?increment(5)       -- shows 6
?increment(5,2)     -- shows 7


def mypower
	1 tolist flatten len
	1 == if
		1 get 2
	else
		2 get swap 1 get rot
	endif
	power
	nip
enddef

"2 ^2 = " print 2 mypower print nl
"2 ^3 = " print 2 3 2 tolist mypower print


(de sortTable (Tbl . @)
   (let (Ordering prog  Column 1  Reverse NIL)  # Set defaults
      (bind (rest)                              # Bind optional params
         (setq Tbl
            (by '((L) (Ordering (get L Column)))
               sort
               Tbl ) )
         (if Reverse (flip Tbl) Tbl) ) ) )


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

>>> import operator
>>> def sorttable(table, ordering=None, column=0, reverse=False):
    return sorted(table, cmp=ordering, key=operator.itemgetter(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"
>>>


tablesort <- function(x, ordering="lexicographic", column=1, reverse=false)
{
   # Implementation
}

# Usage is e.g.
tablesort(mytable, column=3)


#lang racket

(define (sort-table table
                    [ordering string<=?]
                    [column 0]
                    [reverse? #f])
  (sort table (if reverse?
                  (negate ordering)
                  ordering)
        #:key (λ (row) (list-ref row column))))


method sorttable(:$column = 0, :$reverse, :&ordering = &infix:<cmp>) {
    my @result = self»[$column].sort: &ordering;
    return $reverse ?? @result.reverse !! @result;
}


sortStrings:  procedure expose @.                /*the stemmed array is named:    @.    */
col= 1                                           /*set some defaults  (here and below). */
reverse= 'NO'
order= 'LEXICOGRAPHIC'
arg options                                      /*obtain the options  (in uppercase).  */
               do j=1  for words(options)        /*examine all the words (options).     */
               x= word(options, j)
                    select
                    when datatype(x, 'W')  then col= x / 1      /*normalize the number. */
                    when pos('=', x)==0    then order= x        /*has it an equal sign? */
                    otherwise                   parse var x nam '=' value   /*get value.*/
                    end   /*select*/
               end        /*j*/

                         /*╔═══════════════════════════════════════════════════════════╗
                           ║ check for errors here:  COL isn't a positive integer ···, ║
                           ║                         REVERSE value isn't  NO  or  YES, ║
                           ║                         ORDER   value is recognized ···   ║
                           ╚═══════════════════════════════════════════════════════════╝*/

       ... main body of string sort here ...

return                                           /*stick a fork in it,  we're all done. */


def table_sort(table, ordering=:<=>, column=0, reverse=false)
  # ...


use std::cmp::Ordering;

struct Table {
    rows: Vec<Vec<String>>,
    ordering_function: fn(&str, &str) -> Ordering,
    ordering_column: usize,
    reverse: bool,
}

impl Table {
    fn new(rows: Vec<Vec<String>>) -> Table {
        Table {
            rows: rows,
            ordering_column: 0,
            reverse: false,
            ordering_function: |str1, str2| str1.cmp(str2),
        }
    }
}

impl Table {
    fn with_ordering_column(&mut self, ordering_column: usize) -> &mut Table {
        self.ordering_column = ordering_column;
        self
    }

    fn with_reverse(&mut self, reverse: bool) -> &mut Table {
        self.reverse = reverse;
        self
    }

    fn with_ordering_fun(&mut self, compare: fn(&str, &str) -> Ordering) -> &mut Table {
        self.ordering_function = compare;
        self
    }

    fn sort(&mut self) {
        let fun = &mut self.ordering_function;
        let idx = self.ordering_column;
        if self.reverse {
            self.rows
                .sort_unstable_by(|vec1, vec2| (fun)(&vec1[idx], &vec2[idx]).reverse());
        } else {
            self.rows
                .sort_unstable_by(|vec1, vec2| (fun)(&vec1[idx], &vec2[idx]));
        }
    }
}

#[cfg(test)]
mod test {
    use super::Table;

    fn generate_test_table() -> Table {
        Table::new(vec![
            vec!["0".to_string(), "fff".to_string()],
            vec!["2".to_string(), "aab".to_string()],
            vec!["1".to_string(), "ccc".to_string()],
        ])
    }

    #[test]
    fn test_simple_sort() {
        let mut table = generate_test_table();
        table.sort();
        assert_eq!(
            table.rows,
            vec![
                vec!["0".to_string(), "fff".to_string()],
                vec!["1".to_string(), "ccc".to_string()],
                vec!["2".to_string(), "aab".to_string()],
            ],
        )
    }

    #[test]
    fn test_ordering_column() {
        let mut table = generate_test_table();
        table.with_ordering_column(1).sort();
        assert_eq!(
            table.rows,
            vec![
                vec!["2".to_string(), "aab".to_string()],
                vec!["1".to_string(), "ccc".to_string()],
                vec!["0".to_string(), "fff".to_string()],
            ],
        )
    }

    #[test]
    fn test_with_reverse() {
        let mut table = generate_test_table();
        table.with_reverse(true).sort();
        assert_eq!(
            table.rows,
            vec![
                vec!["2".to_string(), "aab".to_string()],
                vec!["1".to_string(), "ccc".to_string()],
                vec!["0".to_string(), "fff".to_string()],
            ],
        )
    }

    #[test]
    fn test_custom_ordering_fun() {
        let mut table = generate_test_table();
        // Simple ordering function that reverses stuff.
        // Should operate like the test before.
        table.with_ordering_fun(|x, y| x.cmp(y).reverse()).sort();
        assert_eq!(
            table.rows,
            vec![
                vec!["2".to_string(), "aab".to_string()],
                vec!["1".to_string(), "ccc".to_string()],
                vec!["0".to_string(), "fff".to_string()],
            ],
        )
    }

    #[test]
    fn test_everything_together() {
        let mut table = generate_test_table();
        // Using the reversing cmp function, then reverse (= don't do anything)
        // then sort from column 1.
        table
            .with_ordering_fun(|x, y| x.cmp(y).reverse())
            .with_reverse(true)
            .with_ordering_column(1)
            .sort();
        assert_eq!(
            table.rows,
            vec![
                vec!["2".to_string(), "aab".to_string()],
                vec!["1".to_string(), "ccc".to_string()],
                vec!["0".to_string(), "fff".to_string()],
            ],
        )
    }
}


  def sortTable(data: List[List[String]],
                ordering: (String, String) => Boolean = (_ < _),
                column: Int = 0,
                reverse: Boolean = false) = {
    val result = data.sortWith((a, b) => ordering(a(column), b(column)))
    if (reverse) result.reverse else result
  }


func table_sort(table, ordering: '<=>', column: 0, reverse: false) {
  if (reverse) {
    table.sort {|a,b| b[column].$ordering(a[column])}
  } else {
    table.sort {|a,b| a[column].$ordering(b[column])}
  }
}

# Quick example:
var table = [
  ["Ottowa", "Canada"],
  ["Washington", "USA"],
  ["Mexico City", "Mexico"],
];

say table_sort(table, column: 1);


[email protected](Sequence traits) tableSort &column: column &sortBy: sortBlock &reverse: reverse
[
  column `defaultsTo: 0.
  sortBlock `defaultsTo: [| :a :b | (a lexicographicallyCompare: b) isNegative].
  (reverse `defaultsTo: False)
    ifTrue: [sortBlock := [| :a :b | (sortBlock applyTo: {a. b}) not]].
  s sortBy: [| :a :b | sortBlock applyTo: {a at: column. b at: column}]
].


enum SortOrder { case kOrdNone, kOrdLex, kOrdByAddress, kOrdNumeric }

func sortTable(table: [[String]], less: (String,String)->Bool = (<), column: Int = 0, reversed: Bool = false) {
  // . . . Actual sort goes here . . .
}


proc tablesort {table {ordering ""} {column 0} {reverse 0}} {
    set direction [expr {$reverse ? "-decreasing" : "-increasing"}]
    if {$ordering ne ""} {
        lsort -command $ordering $direction -index $column $table
    } else {
        lsort $direction -index $column $table
    }
}

puts [tablesort $data]
puts [tablesort $data "" 1]
puts [tablesort $data "" 0 1]
puts [tablesort $data {
    apply {{a b} {expr {[string length $a]-[string length $b]}}}
}]


function sorter(table, ordering = "lexicographic", column = 0, reverse = false) {
    // ...
}

sorter(the_data,"numeric");


#!/usr/bin/env bash
# sort-args.sh

data() {
  cat <<EOF
   123  456  0789
   456 0789  123
  0789  123  456
EOF
}

# sort_table [column NUM | KIND | reverse] ... <INPUT >OUTPUT
# KIND = lexicographical | numeric | human

sort_table() {
  local opts='-b'
  local column=1
  while (( $# > 0 )) ; do
    case "$1" in
      column|col|c)          column=${2?Missing column number} ; shift ;;
      lexicographical|lex|l) opts+=' -d' ;;
      numeric|num|n)         opts+=' -g' ;;
      human|hum|h)           opts+=' -h' ;;
      reverse|rev|r)         opts+=' -r' ;;
    esac
    shift
  done
  eval "sort $opts -k $column,$column -"
}

echo sort defaults          ; data | sort_table
echo sort defaults reverse  ; data | sort_table reverse
echo sort column 2          ; data | sort_table col 2
echo sort column 2 reverse  ; data | sort_table col 2 reverse
echo sort numeric           ; data | sort_table numeric
echo sort numeric reverse   ; data | sort_table numeric reverse


#import std
#import nat

ss ::

ordering   %fZ ~ordering||lleq!
column     %n  ~column||1!
reversed   %b

sorter = +^(~reversed?/~&x! ~&!,-<+ +^/~ordering ~~+ ~&h++ //skip+ predecessor+ ~column)


Private Sub optional_parameters(theRange As String, _
        Optional ordering As Integer = 0, _
        Optional column As Integer = 1, _
        Optional reverse As Integer = 1)
    ActiveSheet.Sort.SortFields.Clear
    ActiveSheet.Sort.SortFields.Add _
        Key:=Range(theRange).Columns(column), _
        SortOn:=SortOnValues, _
        Order:=reverse, _
        DataOption:=ordering 'the optional parameter ordering and above reverse
    With ActiveSheet.Sort
        .SetRange Range(theRange)
        .Header = xlGuess
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With
End Sub
Public Sub main()
    'Sort the strings in the active sheet in Excel
    'Supply the range of cells to be sorted
    'Optionally specify ordering, default is 0,
    'which is normal sort, text and data separately;
    'ordering:=1 treats text as numeric data.
    'Optionally specify column number, default is 1
    'Optionally specify reverse, default is 1
    'which sorts in ascending order.
    'Specifying reverse:=2 will sort in descending order.
    optional_parameters theRange:="A1:C4", ordering:=1, column:=2, reverse:=1
End Sub


import "./sort" for Cmp, Sort
import "./seq" for Lst

class TableSorter {
   // uses 'merge' sort to avoid mutating original table
   // column is zero based
   static sort(table, ordering, column, reverse) {
       if (ordering == null) ordering = Fn.new { |r1, r2| Cmp.string.call(r1[column], r2[column]) }
       var sorted = Sort.merge(table, ordering)
       if (reverse) Lst.reverse(sorted)
       return sorted
   }

   // overloads to simulate optional parameters
   static sort(table)                   { sort(table, null, 0, false) }
   static sort(table, ordering)         { sort(table, ordering, 0, false) }
   static sort(table, ordering, column) { sort(table, ordering, column, false) }
}

var table = [
    ["first", "1"],
    ["second", "2"],
    ["fourth", "4"],
    ["fifth", "5"],
    ["third", "3"]
]

System.print("Original table:")
System.print(table.join("\n"))

System.print("\nAfter lexicographic sort by first column:")
var table2 = TableSorter.sort(table)
System.print(table2.join("\n"))

System.print("\nAfter sorting in length order of first column:")
var ordering = Fn.new { |r1, r2| (r1[0].count - r2[0].count).sign }
table2 = TableSorter.sort(table, ordering)
System.print(table2.join("\n"))

System.print("\nAfter lexicographic sort by second column:")
table2 = TableSorter.sort(table, null, 1)
System.print(table2.join("\n"))

System.print("\nAfter reverse lexicographic sort by second column:")
table2 = TableSorter.sort(table, null, 1, true)
System.print(table2.join("\n"))


<xsl:template name="sort">
  <xsl:param name="table" />
  <xsl:param name="ordering" select="'lexicographic'" />
  <xsl:param name="column" select="1" />
  <xsl:param name="reversed" select="false()" />
  ...
</xsl:template>


sub power(n, p)
	if numparams = 1 p = 2
	return n^p
end sub

print power(2)
print power(2, 3)


const lex="L";
fcn mystrySort(table,ordering=lex,column=0,reverse=False,other){
   vm.arglist.println();
}
mystrySort.prototype.println();
mystrySort("table");
mystrySort("table",lex,1);
mystrySort("table",lex,1,True,D("row",35,"type","foobar"));


V unit2mult = [‘arshin’ = 0.7112, ‘centimeter’ = 0.01,     ‘diuym’   = 0.0254,
               ‘fut’    = 0.3048, ‘kilometer’  = 1000.0,   ‘liniya’  = 0.00254,
               ‘meter’  = 1.0,    ‘milia’      = 7467.6,   ‘piad’    = 0.1778,
               ‘sazhen’ = 2.1336, ‘tochka’     = 0.000254, ‘vershok’ = 0.04445,
               ‘versta’ = 1066.8]

:start:
assert(:argv.len == 3, ‘ERROR. Need two arguments - number then units’)
Float value
X.try
   value = Float(:argv[1])
X.catch
   exit(‘ERROR. First argument must be a (float) number’)
V unit = :argv[2]
assert(unit C unit2mult, ‘ERROR. Only know the following units: ’unit2mult.keys().join(‘ ’))

print(‘#. #. to:’.format(value, unit))
L(unt, mlt) sorted(unit2mult.items())
   print(‘  #10: #.’.format(unt, value * unit2mult[unit] / mlt))


INCLUDE "D2:REAL.ACT" ;from the Action! Tool Kit

DEFINE PTR="CARD"
DEFINE UNIT_COUNT="10"

PTR ARRAY
  names(UNIT_COUNT),
  values(UNIT_COUNT)
BYTE count=[0]

PROC Append(CHAR ARRAY name REAL POINTER value)
  names(count)=name
  values(count)=value
  count==+1
RETURN

PROC Init()
  REAL
    arshin,centimeter,kilometer,meter,
    sazhen,vershok,versta

  ValR("0.7112",arshin)   Append("arshins",arshin)
  ValR("0.01",centimeter) Append("centimeters",centimeter)
  ValR("1000",kilometer)  Append("kilometers",kilometer)
  ValR("1",meter)         Append("meters",meter)
  ValR("2.1336",sazhen)   Append("sazhens",sazhen)
  ValR("0.04445",vershok) Append("vershoks",vershok)
  ValR("1066.8",versta)   Append("versts",versta)
RETURN

BYTE FUNC GetUnit()
  BYTE i,res

  FOR i=1 TO count
  DO
    PrintF("%B-%S",i,names(i-1))
    IF i<count THEN Put(32) FI
  OD
  PutE()
  DO
    PrintF("Get unit (1-%B): ",count)
    res=InputB()
  UNTIL res>=1 AND res<=count
  OD
RETURN (res-1)

PROC PrintResult(REAL POINTER value BYTE unit)
  BYTE i
  REAL res,tmp

  PutE()
  FOR i=0 TO count-1
  DO
    IF i=unit THEN
      RealAssign(value,res)
    ELSE
      RealMult(value,values(unit),tmp)
      RealDiv(tmp,values(i),res)
    FI
    Print("  ") PrintR(res)
    PrintF(" %S%E",names(i))
  OD
  PutE()
RETURN

PROC Main()
  BYTE unit
  REAL value

  Put(125) PutE() ;clear screen
  Init()

  DO
    Print("Get value: ")
    InputR(value)
    unit=GetUnit()
    PrintResult(value,unit)
  OD
RETURN


-- General purpose linear measurement converter.
on convertLinear(inputNumber, inputUnitRecord, outputUnitRecord)
    set {inputType, outputType} to {inputUnitRecord's type, outputUnitRecord's type}
    if (inputType is not outputType) then error "Unit type mismatch: " & inputType & ", " & outputType
    -- The |offset| values are only relevant to temperature conversions and default to zero.
    set inputUnit to inputUnitRecord & {|offset|:0}
    set outputUnit to outputUnitRecord & {|offset|:0}

    return (inputNumber - (inputUnit's |offset|)) * (inputUnit's coefficient) / (outputUnit's coefficient) ¬
        + (outputUnit's |offset|)
end convertLinear

on program(inputNumber, inputUnitName)
    -- The task description only specifies these seven units, but more can be added if wished.
    -- The coefficients are the equivalent lengths in metres.
    set unitRecords to {{|name|:"metre", type:"length", coefficient:1.0}, ¬
        {|name|:"centimetre", type:"length", coefficient:0.01}, {|name|:"kilometre", type:"length", coefficient:1000.0}, ¬
        {|name|:"vershok", type:"length", coefficient:0.04445}, {|name|:"arshin", type:"length", coefficient:0.7112}, ¬
        {|name|:"sazhen", type:"length", coefficient:2.1336}, {|name|:"versta", type:"length", coefficient:1066.8}}

    -- Massage the given input unit name if necessary.
    if (inputUnitName ends with "s") then set inputUnitName to text 1 thru -2 of inputUnitName
    if (inputUnitName ends with "meter") then set inputUnitName to (text 1 thru -3 of inputUnitName) & "re"

    -- Get the record with the input unit name from 'unitRecords'.
    set inputUnitRecord to missing value
    repeat with thisRecord in unitRecords
        if (thisRecord's |name| is inputUnitName) then
            set inputUnitRecord to thisRecord's contents
            exit repeat
        end if
    end repeat
    if (inputUnitRecord is missing value) then error "Unrecognised unit name: " & inputUnitName

    -- Guess the user's spelling preference from the short-date order configured on their machine.
    tell (current date) to set {Feb1, its day, its month, its year} to {it, 1, 2, 3333}
    set USSpelling to (Feb1's short date string's first word as integer is 2)

    -- Convert the input number to its equivalents in all the specified units, rounding to eight decimal
    -- places and getting integer values as AS integers where possible. Pair the results with the unit names.
    set output to {}
    repeat with thisRecord in unitRecords
        set outputNumber to convertLinear(inputNumber, inputUnitRecord, thisRecord)
        set outputNumber to outputNumber div 1 + ((outputNumber * 100000000 mod 100000000) as integer) / 100000000
        if (outputNumber mod 1 is 0) then set outputNumber to outputNumber div 1
        set outputUnitName to thisRecord's |name|
        if ((outputUnitName ends with "metre") and (USSpelling)) then ¬
            set outputUnitName to (text 1 thru -3 of outputUnitName) & "er"
        if (outputNumber is not 1) then set outputUnitName to outputUnitName & "s"
        set end of output to {outputNumber, outputUnitName}
    end repeat

    return output -- {{number, unit name}, … }
end program

on demo()
    set output to {}
    set astid to AppleScript's text item delimiters
    repeat with input in {{1, "kilometre"}, {1, "versta"}}
        set {inputNumber, inputUnitName} to input
        set end of output to (inputNumber as text) & space & inputUnitName & " is:"
        set conversions to program(inputNumber, inputUnitName)
        set AppleScript's text item delimiters to space
        repeat with thisConversion in conversions
            set thisConversion's contents to thisConversion as text
        end repeat
        set AppleScript's text item delimiters to ";  "
        set end of output to conversions as text
    end repeat
    set AppleScript's text item delimiters to linefeed
    set output to output as text
    set AppleScript's text item delimiters to astid

    return output
end demo

return demo()


# syntax: GAWK -f OLD_RUSSIAN_MEASURE_OF_LENGTH.AWK
BEGIN {
    units = "kilometer meter centimeter tochka liniya diuym vershok piad fut arshin sazhen versta milia"
    values = "1000.0 1.0 0.01 0.000254 0.00254 0.0254 0.04445 0.1778 0.3048 0.7112 2.1336 1066.8 7467.6"
    u_leng = split(units,u_arr," ")
    v_leng = split(values,v_arr," ")
    if (u_leng != v_leng) {
      print("error: lengths of units & values are unequal")
      exit(1)
    }
    print("enter length & measure or C/R to exit")
}
{   if ($0 == "") {
      exit(0)
    }
    measure = tolower($2)
    sub(/s$/,"",measure)
    for (i=1; i<=u_leng; i++) {
      if (u_arr[i] == measure) {
        for (j=1; j<=u_leng; j++) {
          str = sprintf("%.8f",$1*v_arr[i]/v_arr[j])
          sub(/0+$/,"",str)
          printf("%10s %s\n",u_arr[j],str)
        }
        print("")
        next
      }
    }
    printf("error: invalid measure; choose from: %s\n\n",units)
}


REM >oldrussian
@% = &90E
PROColdrus(1, "meter")
PRINT
PROColdrus(10, "arshin")
END
:
DEF PROColdrus(length, unit$)
LOCAL units$(), values(), unit%, i%
DIM units$(12)
DIM values(12)
units$() = "kilometer", "meter", "centimeter", "milia", "versta", "sazhen", "arshin", "fut", "piad", "vershok", "diuym", "liniya", "tochka"
values() = 1000, 1, 0.01, 7467.6, 1066.8, 2.1336, 0.7112, 0.3048, 0.1778, 0.04445, 0.0254, 0.00254, 0.000254
unit% = -1
FOR i% = 0 TO 12
  IF units$(i%) = unit$ THEN unit% = i%
NEXT
IF unit% = -1 THEN
  PRINT "Unknown unit '"; unit$; "'"
ELSE
  PRINT; length; " "; unit$; " ="
  FOR i% = 0 TO 12
    IF i% <> unit% THEN PRINT length / values(i%) * values(unit%); " "; units$(i%)
  NEXT
ENDIF
ENDPROC


#include<string.h>
#include<stdlib.h>
#include<ctype.h>
#include<stdio.h>

#define UNITS_LENGTH 13

int main(int argC,char* argV[])
{
	int i,reference;
	char *units[UNITS_LENGTH] = {"kilometer","meter","centimeter","tochka","liniya","diuym","vershok","piad","fut","arshin","sazhen","versta","milia"};
    double factor, values[UNITS_LENGTH] = {1000.0,1.0,0.01,0.000254,0.00254,0.0254,0.04445,0.1778,0.3048,0.7112,2.1336,1066.8,7467.6};

	if(argC!=3)
		printf("Usage : %s followed by length as <value> <unit>");
	else{
		for(i=0;argV[2][i]!=00;i++)
			argV[2][i] = tolower(argV[2][i]);

		for(i=0;i<UNITS_LENGTH;i++){
			if(strstr(argV[2],units[i])!=NULL){
				reference = i;
				factor = atof(argV[1])*values[i];
				break;
			}
		}

		printf("%s %s is equal in length to : \n",argV[1],argV[2]);

		for(i=0;i<UNITS_LENGTH;i++){
			if(i!=reference)
				printf("\n%lf %s",factor/values[i],units[i]);
		}
	}

	return 0;
}


#include <iostream>
#include <iomanip>
//-------------------------------------------------------------------------------------------
using namespace std;

//-------------------------------------------------------------------------------------------
class ormConverter
{
public:
    ormConverter() :  AR( 0.7112f ), CE( 0.01f ), DI( 0.0254f ), FU( 0.3048f ), KI( 1000.0f ), LI( 0.00254f ), ME( 1.0f ),
		      MI( 7467.6f ), PI( 0.1778f ), SA( 2.1336f ), TO( 0.000254f ), VE( 0.04445f ), VR( 1066.8f ) {}
    void convert( char c, float l )
    {
	system( "cls" );
	cout << endl << l;
	switch( c )
	{
	    case 'A': cout << " Arshin to:";     l *= AR; break;
	    case 'C': cout << " Centimeter to:"; l *= CE; break;
	    case 'D': cout << " Diuym to:";      l *= DI; break;
	    case 'F': cout << " Fut to:";        l *= FU; break;
	    case 'K': cout << " Kilometer to:";  l *= KI; break;
	    case 'L': cout << " Liniya to:";     l *= LI; break;
	    case 'M': cout << " Meter to:";      l *= ME; break;
	    case 'I': cout << " Milia to:";      l *= MI; break;
	    case 'P': cout << " Piad to:";       l *= PI; break;
	    case 'S': cout << " Sazhen to:";     l *= SA; break;
	    case 'T': cout << " Tochka to:";     l *= TO; break;
	    case 'V': cout << " Vershok to:";    l *= VE; break;
	    case 'E': cout << " Versta to:";     l *= VR;
	}

	float ar = l / AR, ce = l / CE, di = l / DI, fu = l / FU, ki = l / KI, li = l / LI, me = l / ME,
	      mi = l / MI, pi = l / PI, sa = l / SA, to = l / TO, ve = l / VE, vr = l / VR;
	cout << left << endl << "=================" << endl
	     << setw( 12 ) << "Arshin:" << ar << endl << setw( 12 ) << "Centimeter:" << ce << endl
	     << setw( 12 ) << "Diuym:" << di << endl << setw( 12 ) << "Fut:" << fu << endl
	     << setw( 12 ) << "Kilometer:" << ki << endl << setw( 12 ) << "Liniya:" << li << endl
	     << setw( 12 ) << "Meter:" << me << endl << setw( 12 ) << "Milia:" << mi << endl
	     << setw( 12 ) << "Piad:" << pi << endl << setw( 12 ) << "Sazhen:" << sa << endl
	     << setw( 12 ) << "Tochka:" << to << endl << setw( 12 ) << "Vershok:" << ve << endl
	     << setw( 12 ) << "Versta:" << vr << endl << endl << endl;
    }
private:
    const float AR, CE, DI, FU, KI, LI, ME, MI, PI, SA, TO, VE, VR;
};
//-------------------------------------------------------------------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
    ormConverter c;
    char s; float l;
    while( true )
    {
	cout << "What unit:\n(A)rshin, (C)entimeter, (D)iuym, (F)ut\n(K)ilometer, (L)iniya, (M)eter, m(I)lia, (P)iad\n(S)azhen, (T)ochka, (V)ershok, v(E)rsta, (Q)uit\n";
	cin >> s; if( s & 32 ) s ^= 32; if( s == 'Q' ) return 0;
	cout << "Length (0 to Quit): "; cin >> l; if( l == 0 ) return 0;
	c.convert( s, l ); system( "pause" ); system( "cls" );
    }
    return 0;
}
//-------------------------------------------------------------------------------------------


import std.stdio, std.string, std.algorithm, std.conv;

void main(in string[] args) {
    auto factor = ["arshin":         0.7112,
                   "centimeter":     0.01,
                   "diuym":          0.0254,
                   "fut":            0.3048,
                   "kilometer":  1_000.0,
                   "liniya":         0.00254,
                   "meter":          1.0,
                   "milia":      7_467.6,
                   "piad":           0.1778,
                   "sazhen":         2.1336,
                   "tochka":         0.000254,
                   "vershok":        0.04445,
                   "versta":     1_066.8];

    if (args.length != 3 || !isNumeric(args[1]) || args[2] !in factor)
        return writeln("Please provide args Value and Unit.");

    immutable magnitude = args[1].to!double;
    immutable meters = magnitude * factor[args[2]];
    writefln("%s %s to:\n", args[1], args[2]);
    foreach (immutable key; factor.keys.schwartzSort!(k => factor[k]))
       writefln("%10s: %s", key, meters / factor[key]);
}


program Old_Russian_measure_of_length;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

const
  units: array[0..12] of string = ('tochka', 'liniya', 'dyuim', 'vershok',
    'piad', 'fut', 'arshin', 'sazhen', 'versta', 'milia', 'centimeter', 'meter',
    'kilometer');
  convs: array[0..12] of double = (0.0254, 0.254, 2.54, 4.445, 17.78, 30.48,
    71.12, 213.36, 10668, 74676, 1, 100, 10000);

function ReadInt(): integer;
var
  data: string;
begin
  Readln(data);
  Result := StrToIntDef(data, -1);
end;

function ReadFloat(): Double;
var
  data: string;
begin
  Readln(data);
  Result := StrToFloatDef(data, -1);
end;

var
  yn, u: string;
  i, unt: integer;
  value: Double;

begin

  repeat
    for i := 0 to High(units) do
    begin
      u := units[i];
      Writeln(format('%2d %s', [i + 1, u]));
    end;
    Writeln;

    unt := 0;
    repeat
      Writeln('Please choose a unit 1 to 13 : ');
      unt := ReadInt();
    until (unt >= 1) and (unt <= 13);

    dec(unt);

    repeat
      Writeln('Now enter a value in that unit : ');
      value := ReadFloat();
    until value >= 0;

    Writeln(#10'The equivalent in the remaining units is:'#10);

    for i := 0 to High(units) do
    begin
      u := units[i];
      if i = unt then
        Continue;
      Writeln(format(' %10s : %g', [u, value * convs[unt] / convs[i]]));
    end;

    Writeln;

    yn := '';
    Writeln('Do another one y/n : ');
    readln(yn);
  until yn.toLower = 'n';
end.


import system'collections;
import system'routines;
import extensions;

unit2mult = new Map<string, real>()
    .setAt("arshin",     0.7112r)
    .setAt("centimeter", 0.01r)
    .setAt("diuym",      0.0254r)
    .setAt("fut",        0.3048r)
    .setAt("kilometer",  1000.0r)
    .setAt("liniya",     0.00254r)
    .setAt("meter",      1.0r)
    .setAt("milia",      7467.6r)
    .setAt("piad",       0.1778r)
    .setAt("sazhen",     2.1336r)
    .setAt("tochka",     0.000254r)
    .setAt("vershok",    0.04445r)
    .setAt("versta",     1066.8r);

public program()
{
    if (program_arguments.Length != 3)
        { console.writeLine:"need two arguments - number then units"; AbortException.raise() };

    real value := program_arguments[1].toReal();
    string unit := program_arguments[2];
    ifnot (unit2mult.containsKey(unit))
    {
        console.printLine("only following units are supported:",
            unit2mult.selectBy:(x=>x.Item1).asEnumerable());

        AbortException.raise()
    };

    console.printLine(value," ",unit," to:");

    unit2mult.forEach:(u,mlt)
    {
        console.printPaddingLeft(30, u, ":").printLine(value * unit2mult[unit] / mlt)
    }
}


USING: formatting inverse io kernel math prettyprint quotations
sequences units.imperial units.si vocabs ;
IN: rosetta-code.units.russian

: arshin  ( n -- d ) 2+1/3 * feet ;
: tochka  ( n -- d ) 1/2800 * arshin ;
: liniya  ( n -- d ) 1/280 * arshin ;
: dyuim   ( n -- d ) 1/28 * arshin ;
: vershok ( n -- d ) 1/16 * arshin ;
: ladon   ( n -- d ) 7+1/2 * cm ;
: piad    ( n -- d ) 1/4 * arshin ;
: fut     ( n -- d ) 3/7 * arshin ;
: lokot   ( n -- d ) 45 * cm ;
: shag    ( n -- d ) 71 * cm ;
: sazhen  ( n -- d ) 3 * arshin ;
: versta  ( n -- d ) 1,500 * arshin ;
: milya   ( n -- d ) 10,500 * arshin ;

<PRIVATE

: convert ( quot -- )
    [ unparse rest rest but-last write "to:" print ] [ call ] bi
    "rosetta-code.units.russian" vocab-words { cm m km } append
    [ dup "%8u : " printf 1quotation [undo] call( x -- x ) . ]
    with each nl ; inline

: main ( -- )
    [ 6 m ] [ 1+7/8 milya ] [ 2 furlongs ] [ convert ] [email protected] ;

PRIVATE>

MAIN: main


PROGRAM RUS
 IMPLICIT NONE
 REAL, PARAMETER:: E_m = 1.
 REAL, PARAMETER:: E_mm = 1.E-3
 REAL, PARAMETER:: E_km = 1.E+3
 REAL, PARAMETER:: E_cm = 1.E-2
 REAL, PARAMETER:: E_arshin = 71.12 * E_cm
 REAL, PARAMETER:: E_fut = 3./7. * E_arshin
 REAL, PARAMETER:: E_piad = 1./4. * E_arshin
 REAL, PARAMETER:: E_vershok = 1./16. * E_arshin
 REAL, PARAMETER:: E_dyuim = 1./28. * E_arshin
 REAL, PARAMETER:: E_liniya = 1./280. * E_arshin
 REAL, PARAMETER:: E_tochka = 1./2800. * E_arshin
 REAL, PARAMETER:: E_ladon = 7.5 * E_cm
 REAL, PARAMETER:: E_lokot = 45 * E_cm
 REAL, PARAMETER:: E_sazhen = 3. * E_arshin
 REAL, PARAMETER:: E_versta = 1500. * E_arshin
 REAL, PARAMETER:: E_milya = 10500. * E_arshin
 INTEGER, PARAMETER:: N = 16
 CHARACTER(LEN=7), DIMENSION(N):: nam = (/&
  &'m      ', 'mm     ', 'km     ', 'cm     ',&
  &'arshin ', 'fut    ', 'piad   ', 'vershok',&
  &'dyuim  ', 'liniya ', 'tochka ', 'ladon  ',&
  &'lokot  ', 'sazhen ', 'versta ', 'milya  ' /)
 REAL, DIMENSION(N):: wert = (/ &
  &1., E_mm, E_km, E_cm,&
  &E_arshin, E_fut, E_piad, E_vershok,&
  &E_dyuim, E_liniya, E_tochka, E_ladon,&
  &E_lokot, E_sazhen, E_versta, E_milya /)
 CHARACTER(LEN=7):: RD_U
 REAL:: RD_V
 INTEGER:: I, J
 DO I=1, N
  WRITE(*, '(A, " ")', ADVANCE='NO')  nam(I)
 END DO
 WRITE (*, *)
 WRITE(*, '(A)', ADVANCE='NO') 'value unit -> '
 READ(*, *) RD_V, RD_U
 RD_U = ADJUSTL(RD_U)
 J = 1
 DO WHILE (NAM(J) .NE. RD_U)
  J = J + 1
  IF (J .GT. N) STOP "Unit not known: "//RD_U
 END DO
 RD_V = RD_V * wert(J)
 DO I=1, N
  J = J + 1
  IF (J .GT. N) J = 1
  WRITE (*, '(F20.3, " ", A)') RD_V / wert(J), nam(J)
 END DO
END PROGRAM RUS


' FB 1.05.0 Win64

Dim units(1 To 13) As String = {"tochka", "liniya", "dyuim", "vershok", "piad", "fut", _
                                "arshin", "sazhen", "versta", "milia", _
                                "centimeter", "meter", "kilometer"}

' all expressed in centimeters
Dim convs(1 To 13) As Single = {0.0254, 0.254, 2.54, 4.445, 17.78, 30.48, _
                                71.12, 213.36, 10668, 74676, _
                                1, 100, 10000}
Dim unit As Integer
Dim value As Single
Dim yn As String

Do
  Shell("cls")
  Print
  For i As Integer = 1 To 13
    Print Using "##"; i;
    Print " "; units(i)
  Next
  Print
  Do
    Input "Please choose a unit 1 to 13 : "; unit
  Loop Until unit >= 1 AndAlso unit <= 13
  Print
  Do
    Input "Now enter a value in that unit : "; value
  Loop Until value >= 0
  Print
  Print "The equivalent in the remaining units is : "
  Print
  For i As Integer = 1 To 13
    If i = unit Then Continue For
    Print " "; units(i), " : "; value * convs(unit) / convs(i)
  Next
  Print
  Do
    Input "Do another one y/n : "; yn
    yn = LCase(yn)
  Loop Until yn = "y" OrElse yn = "n"
Loop Until yn = "n"

End


create units s" kilometer" 2, s" meter" 2, s" centimeter" 2, s" tochka" 2, s" liniya" 2, s" diuym" 2, s" vershok" 2, s" piad" 2, s" fut" 2, s" arshin" 2, s" sazhen" 2, s" versta" 2, s" milia" 2,
create values 1000.0e f, 1.0e f, 0.01e f, 0.000254e f, 0.00254e f, 0.0254e f, 0.04445e f, 0.1778e f, 0.3048e f, 0.7112e f, 2.1336e f, 1066.8e f, 7467.6e f,
: unit ( u1 -- caddr u1 )
    units swap 2 cells * + [email protected] ;
: myval ( u1 -- caddr u1 )
    values swap 1 cells * + [email protected] ;
: 2define create 0 , 0 , ;

2define ch_u
variable mlt
variable theunit
: show ( chosen_unit chosen_mutliplier -- )
    ch_u 2!
    mlt f!
    13 0 DO
    ch_u [email protected] i unit compare if
    else mlt [email protected] f. i unit type cr ." ==========="  cr
        i myval theunit f!
        13 0 DO
            ." 	" i unit type ." : " theunit [email protected] i myval f/ mlt [email protected] f* f. cr
        LOOP
    then
    LOOP cr ;
1e s" meter" show
20e s" versta" show
10e s" milia" show


arshin  := (2 + 1/3) ft
vershok := 1/16 arshin
sazhen  := 3 arshin
verst   := 1500 arshin
versta  := verst

do
{
   valstr = input["Enter unit of measure: ", "1 arshin"]
   val = eval[valstr]
   if ! (val conforms length)
      println["$valstr is not a unit of length."]
} until val conforms length

println["$valstr = "]
println["     " + (val -> "arshin")]
println["     " + (val -> "vershok")]
println["     " + (val -> "sazhen")]
println["     " + (val -> "verst")]
println["     " + (val -> "feet")]
println["     " + (val -> "meters")]
println["     " + (val -> "centimeters")]
println["     " + (val -> "kilometers")]


package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
)

func main() {
    units := []string{
        "tochka", "liniya", "dyuim", "vershok", "piad", "fut",
        "arshin", "sazhen", "versta", "milia",
        "centimeter", "meter", "kilometer",
    }

    convs := []float32{
        0.0254, 0.254, 2.54, 4.445, 17.78, 30.48,
        71.12, 213.36, 10668, 74676,
        1, 100, 10000,
    }

    scanner := bufio.NewScanner(os.Stdin)
    for {
        for i, u := range units {
            fmt.Printf("%2d %s\n", i+1, u)
        }
        fmt.Println()
        var unit int
        var err error
        for {
            fmt.Print("Please choose a unit 1 to 13 : ")
            scanner.Scan()
            unit, err = strconv.Atoi(scanner.Text())
            if err == nil && unit >= 1 && unit <= 13 {
                break
            }
        }
        unit--
        var value float64
        for {
            fmt.Print("Now enter a value in that unit : ")
            scanner.Scan()
            value, err = strconv.ParseFloat(scanner.Text(), 32)
            if err == nil && value >= 0 {
                break
            }
        }
        fmt.Println("\nThe equivalent in the remaining units is:\n")
        for i, u := range units {
            if i == unit {
                continue
            }
            fmt.Printf(" %10s : %g\n", u, float32(value)*convs[unit]/convs[i])
        }
        fmt.Println()
        yn := ""
        for yn != "y" && yn != "n" {
            fmt.Print("Do another one y/n : ")
            scanner.Scan()
            yn = strings.ToLower(scanner.Text())
        }
        if yn == "n" {
            return
        }
    }
}


module Main where

import Text.Printf (printf)
import System.Environment (getArgs, getProgName)

tochka     = ("tochka"    , 0.000254)
liniya     = ("liniya"    , 0.00254)
centimeter = ("centimeter", 0.01)
diuym      = ("diuym"     , 0.0254)
vershok    = ("vershok"   , 0.04445)
piad       = ("piad"      , 0.1778)
fut        = ("fut"       , 0.3048)
arshin     = ("arshin"    , 0.7112)
meter      = ("meter"     , 1.0)
sazhen     = ("sazhen"    , 2.1336)
kilometer  = ("kilometer" , 1000.0)
versta     = ("versta"    , 1066.8)
milia      = ("milia"     , 7467.6)

units :: [(String, Double)]
units = [tochka, liniya, centimeter, diuym, vershok, piad, fut, arshin, meter, sazhen, kilometer, versta, milia]

convert :: Double -> Double -> IO ()
convert num factor = mapM_ (\(unit, fac) -> printf "| %-10s | %-22f|\n" unit  (num * factor / fac)) units

main :: IO ()
main = do
  args <- getArgs
  case args of
    [x,y] | [(num, "")]   <- reads x :: [(Double, String)]
          , (Just factor) <- lookup y units -> convert num factor
    (_) -> do
      name <- getProgName
      printf "Arguments were wrong - please use ./%s <number> <unit>\n" name


NB. Use, linux.
NB. $ /usr/local/j64-801/bin/jconsole j.ijs 8 meter

UNIT2MULT =: /:~ _ ".&.>@:{:@:]`1:`]}"1<;._2@:(,&':');._2 'arshin:0.7112,centimeter:0.01,diuym:0.0254,fut:0.3048,kilometer:1000.0,liniya:0.00254,meter:1.0,milia:7467.6,piad:0.1778,sazhen:2.1336,tochka:0.000254,vershok:0.04445,versta:1066.8,'

exit 3 : 0 :: 1: a: -.~ _3 {. ARGV
 if. 3 ~: # y do. smoutput 'ERROR. Need two arguments - number then units'
 else.
  VALUE =: _ ". _2 {:: y
  if. _ = | VALUE do. smoutput 'ERROR. First argument must be a (float) number'
  else.
   UNIT =: {: y
   UNITS =: 0&{"1 UNIT2MULT
   if. [email protected]:e.UNITS do. smoutput 'ERROR. Only know the following units: ' , deb , ,&' '&> UNITS
   else.
    smoutput deb(,,&' '&>_2{.y),'to:'
    smoutput UNITS ,. (VALUE * (< 1 ,~ UNITS i. UNIT) {:: UNIT2MULT) %&.> {:"1 UNIT2MULT
   end.
  end.
 end.
)


public class OldRussianMeasures {

    final static String[] keys = {"tochka", "liniya", "centimeter", "diuym",
        "vershok", "piad", "fut", "arshin", "meter", "sazhen", "kilometer",
        "versta", "milia"};

    final static double[] values = {0.000254, 0.00254, 0.01,0.0254,
        0.04445, 0.1778, 0.3048, 0.7112, 1.0, 2.1336, 1000.0,
        1066.8, 7467.6};

    public static void main(String[] a) {
        if (a.length == 2 && a[0].matches("[+-]?\\d*(\\.\\d+)?")) {
            double inputVal = lookup(a[1]);
            if (!Double.isNaN(inputVal)) {
                double magnitude = Double.parseDouble(a[0]);
                double meters = magnitude * inputVal;
                System.out.printf("%s %s to: %n%n", a[0], a[1]);
                for (String k: keys)
                    System.out.printf("%10s: %g%n", k, meters / lookup(k));
                return;
            }
        }
        System.out.println("Please provide a number and unit");

    }

    public static double lookup(String key) {
        for (int i = 0; i < keys.length; i++)
            if (keys[i].equals(key))
                return values[i];
        return Double.NaN;
    }
}


using DataStructures

const unit2mult = Dict(
    "arshin" => 0.7112, "centimeter" => 0.01,     "diuym"   => 0.0254,
    "fut"    => 0.3048, "kilometer"  => 1000.0,   "liniya"  => 0.00254,
    "meter"  => 1.0,    "milia"      => 7467.6,   "piad"    => 0.1778,
    "sazhen" => 2.1336, "tochka"     => 0.000254, "vershok" => 0.04445,
    "versta" => 1066.8)

@assert length(ARGS) == 2 "need two arguments - number then units"

global value
try value = parse(Float64, ARGS[1])
catch error("first argument must be a (float) number") end

if isnull(value) error("first argument must be a (float) number") end
unit = ARGS[2]
@assert unit ∈ keys(unit2mult) "only know the following units:\n" * join(keys(unit2mult), ", ")

println("$value $unit to:")
for (unt, mlt) in sort(unit2mult)
    @printf("  %10s: %g\n", unt, value * unit2mult[unit] / mlt)
end


// version 1.0.6

/* clears console on Windows 10 */
fun cls() = ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor()

fun main(args: Array<String>) {
    val units = listOf("tochka", "liniya", "dyuim", "vershok", "piad", "fut",
                       "arshin", "sazhen", "versta", "milia",
                       "centimeter", "meter", "kilometer")
    val convs = arrayOf(0.0254f, 0.254f, 2.54f, 4.445f, 17.78f, 30.48f,
                        71.12f, 213.36f, 10668.0f, 74676.0f,
                        1.0f, 100.0f, 10000.0f)
    var unit: Int
    var value: Float
    var yn : String
    do {
        cls()
        println()
        for (i in 0 until units.size) println("${"%2d".format(i + 1)} ${units[i]}")
        println()
        do {
            print("Please choose a unit 1 to 13 : ")
            unit = try { readLine()!!.toInt() } catch (e: NumberFormatException) { 0 }
        }
        while (unit !in 1..13)
        unit--
        do {
            print("Now enter a value in that unit : ")
            value = try { readLine()!!.toFloat() } catch (e: NumberFormatException) { -1.0f }
        }
        while (value < 0.0f)
        println("\nThe equivalent in the remaining units is:\n")
        for (i in 0 until units.size) {
            if (i == unit) continue
            println(" ${units[i].padEnd(10)} : ${value * convs[unit] / convs[i]}")
        }
        println()
        do {
            print("Do another one y/n : ")
            yn = readLine()!!.toLowerCase()
        }
        while (yn != "y" && yn != "n")
    }
    while (yn == "y")
}


ClearAll[units, ConvertRussianQuantities]
units = {"RussianVershoks", "RussianArshins", "RussianSazhens", "RussianVerstas", "Centimeters", "Meters", "Kilometers"};
ConvertRussianQuantities[q_Quantity] := UnitConvert[q, #] & /@ Select[units, QuantityUnit[q] != # &]
ConvertRussianQuantities[Quantity[1, "Vershoks"]]
ConvertRussianQuantities[Quantity[1, "Arshins"]]


import os, strutils, sequtils, tables

const Unit2Mult = {"arshin": 0.7112, "centimeter": 0.01,     "diuym":   0.0254,
                   "fut":    0.3048, "kilometer":  1000.0,   "liniya":  0.00254,
                   "meter":  1.0,    "milia":      7467.6,   "piad":    0.1778,
                   "sazhen": 2.1336, "tochka":     0.000254, "vershok": 0.04445,
                   "versta": 1066.8}.toOrderedTable

if paramCount() != 2:
  raise newException(ValueError, "need two arguments: number then units.")

let value = try: parseFloat(paramStr(1))
            except ValueError:
              raise newException(ValueError, "first argument must be a (float) number.")

let unit = paramStr(2)
if unit notin Unit2Mult:
  raise newException(ValueError,
                     "only know the following units: " & toSeq(Unit2Mult.keys).join(" "))

echo value, ' ', unit, " to:"
for (key, mult) in Unit2Mult.pairs:
  echo key.align(10), ": ", formatFloat(value * Unit2Mult[unit] / mult, ffDecimal, 5)


sub convert {
    my($magnitude, $unit) = @_;
     my %factor = (
        tochka     => 0.000254,
        liniya     => 0.00254,
        diuym      => 0.0254,
        vershok    => 0.04445,
        piad       => 0.1778,
        fut        => 0.3048,
        arshin     => 0.7112,
        sazhen     => 2.1336,
        versta     => 1066.8,
        milia      => 7467.6,
        centimeter => 0.01,
        meter      => 1.0,
        kilometer  => 1000.0,
    );

    my $base= $magnitude * $factor{$unit};
    my $result .= "$magnitude $unit to:\n";
    for (sort { $factor{$a} <=> $factor{$b} } keys %factor) {
        $result .= sprintf "%10s: %s\n", $_, sigdig($base / $factor{$_}, 5) unless $_ eq $unit
    }
    return $result;
}

sub sigdig {
    my($num,$sig) = @_;
    return $num unless $num =~ /\./;

    $num =~ /([1-9]\d*\.?\d*)/;
    my $prefix = $`;
    my $match  = $&;
    $sig++ if $match =~ /\./;
    my $digits = substr $match, 0, $sig;
    my $nextd  = substr $match, $sig, 1;
    $digits =~ s/(.)$/{1+$1}/e if $nextd > 5;
    return $prefix . $digits;
}

print convert(1,'meter'), "\n\n";
print convert(1,'milia'), "\n";


with javascript_semantics
constant units = {{"-- metric ---",0},
                  {"kilometer",1000},
                  {"km","kilometer"},
                  {"meter",1},
                  {"m","meter"},
                  {"centimeter",0.01},
                  {"cm","centimeter"},
                  {" old russian ",0},
                  {"tochka",0.000254},
                  {"liniya",0.00254},
                  {"diuym",0.0254},
                  {"vershok",0.04445},
                  {"piad",0.1778},
                  {"fut",0.3048},
                  {"arshin",0.7112},
                  {"sazhen",2.1336},
                  {"versta",1066.8},
                  {"milia",7467.6}},
        {names,facts} = columnize(units)

function strim(atom v)
    string res = sprintf("%,f",v)
    integer l = length(res)
    while l do
        integer c = res[l]
        if c!='0' then
            l -= 1+(c='.')
            exit
        end if
        l -= 1
    end while
    res = res[1..l+1]
    return res
end function

-- Obviously, uncomment these lines for a prompt (not under p2js)
--while true do
--  string input = prompt_string("\nEnter length & measure or CR to exit:")
--  if input="" then exit end if
--  input = lower(trim(input))
    string input = "7.4676 km"
    string fmt = iff(find(' ',input)?"%f %s":"%f%s")
    sequence r = scanf(input,fmt)
    if length(r)!=1 then
        printf(1,"enter eg 1km or 1 kilometer\n")
    else
        {atom v, string name} = r[1]
        integer k = find(name,names)
        if k=0 or facts[k]=0 then
            printf(1,"unrecognised unit: %s\n",{name})
        else
            if string(facts[k]) then
                -- abbreviation, eg cm->centimeter
                k = find(facts[k],names)
            end if
            for i=1 to length(names) do
                object f = facts[i]
                if f=0 then             -- header
                    printf(1,"--------------%s--------------\n",{names[i]})
                elsif atom(facts[i]) then -- not abbrev
                    printf(1,"%20s %s\n",{strim(v*facts[k]/facts[i]),names[i]})
                end if
            end for
        end if
    end if
--end while


from sys import argv

unit2mult = {"arshin": 0.7112, "centimeter": 0.01,     "diuym":   0.0254,
             "fut":    0.3048, "kilometer":  1000.0,   "liniya":  0.00254,
             "meter":  1.0,    "milia":      7467.6,   "piad":    0.1778,
             "sazhen": 2.1336, "tochka":     0.000254, "vershok": 0.04445,
             "versta": 1066.8}

if __name__ == '__main__':
    assert len(argv) == 3, 'ERROR. Need two arguments - number then units'
    try:
        value = float(argv[1])
    except:
        print('ERROR. First argument must be a (float) number')
        raise
    unit = argv[2]
    assert unit in unit2mult, ( 'ERROR. Only know the following units: '
                                + ' '.join(unit2mult.keys()) )

    print("%g %s to:" % (value, unit))
    for unt, mlt in sorted(unit2mult.items()):
        print('  %10s: %g' % (unt, value * unit2mult[unit] / mlt))


#lang racket

(define units
  '([tochka        0.000254]
    [liniya        0.00254]
    [diuym         0.0254]
    [vershok       0.04445]
    [piad          0.1778]
    [fut           0.3048]
    [arshin        0.7112]
    [sazhen        2.1336]
    [versta     1066.8]
    [milia      7467.6]
    [centimeter    0.01]
    [meter         1.0]
    [kilometer  1000.0]))

(define (show u)
  (printf "1 ~s to:\n" u)
  (define n (cadr (assq u units)))
  (for ([u2 units] #:unless (eq? u (car u2)))
    (displayln (~a (~a (car u2) #:width 10 #:align 'right) ": "
                   (~r (/ n (cadr u2)) #:precision 4))))
  (newline))

(show 'meter)
(show 'milia)


convert(1, 'meter');

say '*' x 40, "\n";

convert(1, 'milia');

sub convert (Real $magnitude, $unit) {
     my %factor =
        tochka     => 0.000254,
        liniya     => 0.00254,
        diuym      => 0.0254,
        vershok    => 0.04445,
        piad       => 0.1778,
        fut        => 0.3048,
        arshin     => 0.7112,
        sazhen     => 2.1336,
        versta     => 1066.8,
        milia      => 7467.6,
        centimeter => 0.01,
        meter      => 1.0,
        kilometer  => 1000.0,
    ;

    my $meters = $magnitude * %factor{$unit.lc};

    say "$magnitude $unit to:\n", '_' x 40;

    printf "%10s: %s\n", $_,  $meters / %factor{$_} unless $_ eq $unit.lc
      for %factor.keys.sort:{ +%factor{$_} }
}


/*REXX program converts a   metric  or  old Russian length   to various other lengths.  */
                              numeric digits 200                      /*lots of digits. */
  /*──translation───*/
  /*tip, top        */        vershok  = 22.492971                    /*1.75 inch.      */
  /*palm, quarter   */        piad     = vershok    /   4             /*(also) chetvert.*/
  /*yard            */        arshin   = vershok    /  16
  /*fathom          */        sazhen   = arshin     /   3
  /*turn (of a plow)*/        verst    = sazhen     / 500             /*(also) a versta.*/
  /*mile            */        milia    = verst      /   1.5
  /*inch            */        diuym    = arshin     *  28
  /*foot            */        fut      = diuym      /  12             /*sounds like foot*/
  /*line            */        liniya   = diuym      *  10
  /*point           */        tochka   = diuym      * 100

KM= 1000;           CM=100                       /*define a couple of metric multipliers*/
sw= linesize() -1                                /*get the linesize (screen width)  - 1.*/
parse arg N what _ __                            /*obtain the user's input from the C.L.*/
if N==''               then call  err  'no arguments specified.'
if \datatype(N, 'N')   then call  err  'units not numeric: '    N
if _\==''              then call  err  'too many arguments specified: '   _   __
n= n / 1                                         /*normalize it  (004──►4  7.──►7,  etc.*/
if what==''  then what= 'meters';   whatU= what  /*None specified?  Then assume meters. */
upper whatU                                      /*an uppercase version for ABBREV bif. */
                         select                  /* [↓]  convert the length ───► meters.*/
                         when abbrev('METRES'     , whatU    )  |,
                              abbrev('METERS'     , whatU    )       then  m= N
                         when abbrev('KILOMETRES' , whatU, 2 )  |,
                              abbrev('KILOMETERS' , whatU, 2 )  |,
                              abbrev('KMS'        , whatU,   )       then  m= N * KM
                         when abbrev('CENTIMETRES', whatU, 2 )  |,
                              abbrev('CENTIMETERS', whatU, 2 )  |,
                              abbrev('CMS'        , whatU, 2 )       then  m= N / CM
                         when abbrev('ARSHINS'    , whatU    )       then  m= N / arshin
                         when abbrev('DIUYM'      , whatU    )       then  m= N / diuym
                         when abbrev('FUT'        , whatU    )       then  m= N / fut
                         when abbrev('LINIYA'     , whatU    )       then  m= N / liniya
                         when abbrev('PIADS'      , whatU    )  |,
                              abbrev('CHETVERTS'  , whatU, 2 )       then  m= N / piad
                         when abbrev('SAZHENS'    , whatU    )       then  m= N / sazhen
                         when abbrev('TOCHKA'     , whatU    )       then  m= N / tochka
                         when abbrev('VERSHOKS'   , whatU, 5 )       then  m= N / vershok
                         when abbrev('VERSTAS'    , whatU, 5 )  |,
                              abbrev('VERSTS'     , whatU, 2 )       then  m= N / verst
                         when abbrev('MILIA'      , whatU, 2 )       then  m= N / milia
                         otherwise     call err   'invalid measure name: '        what
                         end   /*select*/
                                             say centre('metric',      sw, "─")
call tell m / KM       ,   'kilometer'
call tell m            ,   'meter'
call tell m * CM       ,   'centimeter'
                                             say centre('old Russian', sw, "─")
call tell m * milia    ,   'milia'
call tell m * verst    ,   'verst'
call tell m * sazhen   ,   'sazhen'
call tell m * arshin   ,   'arshin'
call tell m * fut      ,   'fut'
call tell m * piad     ,   'piad'
call tell m * vershok  ,   'vershok'
call tell m * diuym    ,   'diuym'
call tell m * liniya   ,   'liniya'
call tell m * tochka   ,   'tochka'              /* ◄─── TELL shows eight decimal digits*/
exit 0                                           /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
err:  say center(' error ', sw % 2, "*");   do j=1  to arg();  say arg(j);  end;   exit 13
s:    if arg(1)=1  then return arg(3);      return word( arg(2) 's', 1)       /*plurals.*/
tell: parse arg $;  numeric digits 8;  $= $ / 1;  say right($, 40) arg(2)s($);      return/*REXX program converts a   metric  or  old Russian length   to various other lengths.  */
                              numeric digits 200                      /*lots of digits. */
  /*──translation───*/
  /*tip, top        */        vershok  = 22.492971                    /*1.75 inch.      */
  /*palm, quarter   */        piad     = vershok    /   4             /*(also) chetvert.*/
  /*yard            */        arshin   = vershok    /  16
  /*fathom          */        sazhen   = arshin     /   3
  /*turn (of a plow)*/        verst    = sazhen     / 500             /*(also) a versta.*/
  /*mile            */        milia    = verst      /   1.5
  /*inch            */        diuym    = arshin     *  28
  /*foot            */        fut      = diuym      /  12             /*sounds like foot*/
  /*line            */        liniya   = diuym      *  10
  /*point           */        tochka   = diuym      * 100

KM= 1000;           CM=100                       /*define a couple of metric multipliers*/
sw= linesize() -1                                /*get the linesize (screen width)  - 1.*/
parse arg N what _ __                            /*obtain the user's input from the C.L.*/
if N==''               then call  err  'no arguments specified.'
if \datatype(N, 'N')   then call  err  'units not numeric: '    N
if _\==''              then call  err  'too many arguments specified: '   _   __
n= n / 1                                         /*normalize it  (004──►4  7.──►7,  etc.*/
if what==''  then what= 'meters';   whatU= what  /*None specified?  Then assume meters. */
upper whatU                                      /*an uppercase version for ABBREV bif. */
                         select                  /* [↓]  convert the length ───► meters.*/
                         when abbrev('METRES'     , whatU    )  |,
                              abbrev('METERS'     , whatU    )       then  m= N
                         when abbrev('KILOMETRES' , whatU, 2 )  |,
                              abbrev('KILOMETERS' , whatU, 2 )  |,
                              abbrev('KMS'        , whatU,   )       then  m= N * KM
                         when abbrev('CENTIMETRES', whatU, 2 )  |,
                              abbrev('CENTIMETERS', whatU, 2 )  |,
                              abbrev('CMS'        , whatU, 2 )       then  m= N / CM
                         when abbrev('ARSHINS'    , whatU    )       then  m= N / arshin
                         when abbrev('DIUYM'      , whatU    )       then  m= N / diuym
                         when abbrev('FUT'        , whatU    )       then  m= N / fut
                         when abbrev('LINIYA'     , whatU    )       then  m= N / liniya
                         when abbrev('PIADS'      , whatU    )  |,
                              abbrev('CHETVERTS'  , whatU, 2 )       then  m= N / piad
                         when abbrev('SAZHENS'    , whatU    )       then  m= N / sazhen
                         when abbrev('TOCHKA'     , whatU    )       then  m= N / tochka
                         when abbrev('VERSHOKS'   , whatU, 5 )       then  m= N / vershok
                         when abbrev('VERSTAS'    , whatU, 5 )  |,
                              abbrev('VERSTS'     , whatU, 2 )       then  m= N / verst
                         when abbrev('MILIA'      , whatU, 2 )       then  m= N / milia
                         otherwise     call err   'invalid measure name: '        what
                         end   /*select*/
                                             say centre('metric',      sw, "─")
call tell m / KM       ,   'kilometer'
call tell m            ,   'meter'
call tell m * CM       ,   'centimeter'
                                             say centre('old Russian', sw, "─")
call tell m * milia    ,   'milia'
call tell m * verst    ,   'verst'
call tell m * sazhen   ,   'sazhen'
call tell m * arshin   ,   'arshin'
call tell m * fut      ,   'fut'
call tell m * piad     ,   'piad'
call tell m * vershok  ,   'vershok'
call tell m * diuym    ,   'diuym'
call tell m * liniya   ,   'liniya'
call tell m * tochka   ,   'tochka'              /* ◄─── TELL shows eight decimal digits*/
exit 0                                           /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
err:  say center(' error ', sw % 2, "*");   do j=1  to arg();  say arg(j);  end;   exit 13
s:    if arg(1)=1  then return arg(3);      return word( arg(2) 's', 1)       /*plurals.*/
tell: parse arg $;  numeric digits 8;  $= $ / 1;  say right($, 40) arg(2)s($);      return


# Project : Old Russian measure of length

decimals(7)
units = ["tochka", "liniya", "dyuim", "vershok", "piad", "fut",
             "arshin", "sazhen", "versta", "milia",
             "centimeter", "meter", "kilometer"]

convs = [0.0254, 0.254, 2.54, 4.445, 17.78, 30.48,
             71.12, 213.36, 10668, 74676,
             1, 100, 10000]

yn = "y"
unit = 1
p = 1
while yn != "n"
      for i = 1 to 13
          see "" + i + " " + units[i] + nl
      next
      see nl
      see "please choose a unit 1 to 13 : "
      give unit
      see nl
      see "now enter a value in that unit : "
      give value
      see nl
      see "the equivalent in the remaining units is : "
      see nl
      for i = 1 to 13
          if i = unit
             loop
          ok
          see "" + units[i] + " : " + (value * convs[number(unit)] / convs[i]) + nl
      next
      see nl
      while yn = "y" or yn = "n"
              see "do another one y/n : "
              give yn
              yn = lower(yn)
      end
end


module Distances

  RATIOS =
  {arshin: 0.7112, centimeter: 0.01,     diuym:   0.0254,
   fut:    0.3048, kilometer:  1000.0,   liniya:  0.00254,
   meter:  1.0,    milia:      7467.6,   piad:    0.1778,
   sazhen: 2.1336, tochka:     0.000254, vershok: 0.04445,
   versta: 1066.8}

  def self.method_missing(meth, arg)
    from, to = meth.to_s.split("2").map(&:to_sym)
    raise NoMethodError, meth if ([from,to]-RATIOS.keys).size > 0
    RATIOS[from] * arg / RATIOS[to]
  end

  def self.print_others(name, num)
    puts "#{num} #{name} ="
    RATIOS.except(name.to_sym).each {|k,v| puts "#{ (1.0 / v*num)} #{k}" }
  end
end

Distances.print_others("meter", 2)
puts
p Distances.meter2centimeter(3)
p Distances.arshin2meter(1)
p Distances.versta2kilometer(20) # en Hoeperdepoep zat op de stoep
# 13*13 = 169 methods supported, but not:
p Distances.mile2piad(1)


use std::env;
use std::process;
use std::collections::HashMap;

fn main() {

	let units: HashMap<&str, f32> = [("arshin",0.7112),("centimeter",0.01),("diuym",0.0254),("fut",0.3048),("kilometer",1000.0),("liniya",0.00254),("meter",1.0),("milia",7467.6),("piad",0.1778),("sazhen",2.1336),("tochka",0.000254),("vershok",0.04445),("versta",1066.8)].iter().cloned().collect();

	let args: Vec<String> = env::args().collect();
	if args.len() < 3 {
		eprintln!("A correct use is oldrus [amount] [unit].");
		process::exit(1);
	};

	let length_float;
	length_float = match args[1].parse::<f32>() {
		Ok(length_float) =>  length_float,
		Err(..) => 1 as f32,
	};

	let unit: &str = &args[2];
	if ! units.contains_key(unit) {
		let mut keys: Vec<&str> = Vec::new();
		for i in units.keys() {
			keys.push(i)
		};
		eprintln!("The correct units are: {}.", keys.join(", "));
		process::exit(1);
	};

	println!("{} {} to:", length_float, unit);
	for (lunit, length) in &units {
		println!("	{}: {:?}", lunit,  length_float * units.get(unit).unwrap() / length);
	};

}


import scala.collection.immutable.HashMap

object OldRussianLengths extends App {

  private def measures = HashMap("tochka" -> 0.000254,
    "liniya"-> 0.000254, "centimeter"-> 0.01,    "diuym"-> 0.0254, "vershok"-> 0.04445,
    "piad"  -> 0.1778,   "fut"       -> 0.3048, "arshin"-> 0.7112, "meter"  -> 1.0,
    "sazhen"-> 2.1336,   "kilometer" -> 1000.0, "versta"-> 1066.8, "milia"  -> 7467.6
  ).withDefaultValue(Double.NaN)

  if (args.length == 2 && args(0).matches("[+-]?\\d*(\\.\\d+)?")) {
    val inputVal = measures(args(1))

    def meters = args(0).toDouble * inputVal

    if (!java.lang.Double.isNaN(inputVal)) {
      printf("%s %s to: %n%n", args(0), args(1))
      for (k <- measures) println(f"${k._1}%10s:  ${meters / k._2}%g")
    }
  } else println("Please provide a number and unit on the command line.")

}