CPS 343/543 Lecture notes: Course reflection
- a homoiconic language is one which uses the same
representation for programs and data, thus, permitting programs
to be created, modified, and executed at run-time [PLP] p. 552
- homoiconic languages facilitate metaprogramming
(developing programs which create and manipulate other programs or
extend themselves) by obviating the need to translate between
internal (data structure) and external (syntactic) representations of
programs [PLP] p. 575
- LISP, PROLOG, XSLT, Tcl, FORTH, and Snobol are homoiconic
- on the other hand, ML and Haskell are not homoiconic languages
Languages for designing languages
- we studied how to build recursion into a language without
recursion using the applicative-order Y combinator
- we studied how to build any control abstraction (e.g., iteration,
conditionals, repetition, co-routines, threads, lazy-evaluation, gotos) using
first-class continuations ([OCWC])
``...we must not use recursion in the implementation language to implement
recursion in the language being interpreted. ... The reason for this is that
if the implementation language does not support certain kinds of
control structures, then we will not be able to effectively interpret
them. Thus, for example, if the control frame structure in the implementation
language is constrained to be stack-like, then modeling more
general control structures in the interpreted language will be very difficult
unless we divorce ourselves from the constrained structures at the outset''
([SIELC], p. 428).
UD house diagram
- relationship between languages and the capacity to express ideas
- static (rigid and fast) vs. dynamic (flexible and slow) properties
- cost/speed of execution vs. cost/speed of development
- simple and powerful languages
(LISP, Smalltalk) vs. complex and weak languages (so called
kitchen-sink languages [PLPP] (e.g., C++))
- languages evolve:
the influence of language design and implementation options on current trends
in programming practice and vice versa (iPod, GPS in car)
- shift in modern times towards more functional, dynamic languages
(speed of execution is less important as a design goal
as it once was)
(common thread: dynamism)
Slow paradigm shift
(e-mail me with updates when available)
- first-class procedures: Scheme, ML, Haskell → Fortress, Ruby, Python
- first-class closures: LISP → Ruby
- higher-order and anonymous (λ) functions:
LISP → Ruby, Python, R, C++, C#
- first-class continuations: Scheme → Ruby
- dynamic scoping: LISP → Perl, Tcl/Tk
Algol60 → Haskell (call-by-need), R (call-by-need)
- list comprehensions: Haskell → Python
- strong typing: ML, Haskell → Java, C#
- implicit dereferencing: LISP, Smalltalk → Java
- pure OO language: Smalltalk → Ruby
- dynamic binding: Smalltalk → Java, Python
- reflection: Smalltalk → Java, Ruby, Perl, Python, Tcl/Tk, C#
- homoiconic: LISP, PROLOG, FORTH → Tcl, XSLT
Ruby is the closest language to encompassing all of these concepts.
Why are we seeing a trend toward more dynamic languages?
Software engineering, extreme programming, and so on. Efficiency is no longer
the overriding design goal.
We should not think of LISP and Smalltalk as languages, but rather
research projects which pioneered paradigms and language concepts.
- establish an understanding of language concepts through
the implementation of interpreters
- improve ability to understand new languages and technologies,
and improve background for selecting appropriate languages
- expose students to alternate styles of programming and
exotic ways of affecting computation
Advantages of this course of study
(or `why bother with this stuff anyway?')
- see [COPL] §1.1 (pp. 2-5)
- improve background for choosing appropriate languages
- ability to easily learn new languages and technologies as they arrive
(ability to focus on the big picture and not the details)
- some things cannot be expressed as easily in certain languages
- increase capacity to express ideas about computation (thinking
out of the box)
- why these languages?
- increase ability to design and implement new languages
- to better appreciate the historical context
- to become a well-rounded computer scientist
- in summary, this course will make you a better programmer,
in any language
||C.T. Haynes, D.P. Friedman and M. Wand.
Obtaining Coroutines With Continuations. Computer Languages,
11(3/4), 143-153, 1986.
Programming Language Pragmatics.
Morgan Kaufmann, Amsterdam, Second edition, 2006.
||G.J. Sussman and G.L. Steele Jr.
Scheme: An Interpreter for Extended
Lambda Calculus. Higher-Order and Symbolic Computation, 11, 405-439,