{menu: {min_levels: 3}}
Talks briefly about Kay’s Vivarium Project… TODO: find out more
Framer provides a single structure, the frame, out of which more complicated structures are built. A frame has a name and a location within a structure that is similar to a hierarchical file system. All frames except the root have a container or home frame and may also have contained frames or annotations. Frames also have an optional value (which may be any Lisp object, including another frame) and an optional prototype (which must be a frame).
The advantages of prototype-based programming are simplicity and concreteness. It eliminates a whole set of objects (class descriptors) from the environment, and simplifies the specification of inherited properties. In a sense it is specification by example.
There are some indications that mental representation of categories makes use of prototypes
Self [14] is currently the prototypical prototype-based object-oriented programming system. LiveWorld's (really Framer's) major contribution over and above what Self provides is in making slots be first-class objects and thus enabling recursive annotation and containment.
Chang, B.-W. and Ungar, D. Animation: From Cartoons to the User Interface. In Proceedings of UIST `93. (November 3-5, Atlanta, Georgia), 1993, pp. 45-56.
Kay, A. Vivarium Papers. Unpublished essays, 1990.
Lieberman, H. Using Prototypical Objects to Implement Shared Behavior in Object Oriented Systems. In Proceedings of First ACM Conference on Object Oriented Programming Systems, Languages & Application., 1986.
Jini allows anything with a processor, some memory, and a network connection to offer services to other entities on the network or to use the services that are so offered.
Java… (good quote for JoC 2nd ed.)
Java’s most basic property is that it turns an otherwise heterogeneous network of computing entities into a homogeneous collection of Java virtual machines.
Wow! Incredibly prescient!
Describes something called “skeletons and techniques”. Not sure what it means based on this paper.
N. Davies, S. Wade, A. Friday and G. S. Blair, “Limbo: A Tuple Space Based Platform for Adaptive Mobile Applications”, Proceedings of the International Conference on Open Distributed Processing/Distributed Platforms (ICODP/ICDP ‘97), Toronto, Canada, 27-30 May 1997. Internal report number MPG-97-02.
D. Gelernter, “Generative Communication in Linda.”, ACM Transactions on Programming Langauges and Systems, Vol. 7 No. 1, Pages 80-112. January 1985.
D. Gelernter, N. Carriero, S. Chandran and S. Chang, “Parallel Programming in Linda”, Proceedings of the International Conference on Parallel Processing, pp 255-263, August 1985.
CLOS-based generic function (as opposed to message passing) object system.
TODO: Not sure that I understand row-polymorphism.
BCPL -> B -> C
The original UNIX was in assembler, developed on another platform. Thompson did not move to the PDP-7 until he had created the foloowing:
Doug McIlroy created the first HL-language TMG – a lang for writing compilers
Did these guys get paid to just sit around and do awesome stuff?!
They say they wish to “introduce”, but then they use terms as if I know them. :-(
Talks about AspectC
The gist:
Different things should have different names
Shows a nice rename feature of Eiffel.
LOL
the first case of defining a language’s semantics through compiler warnings. Semantics should be defined very precisely, since it conditions the validity of programs and the effect of valid programs
Using functions to gain more expressiveness in conditions.
Quality First is bottom-up (it starts with perfecting a small system then adds functionality)
Motto:
Build it so you can trust it. Then don’t trust it
On comments, etc.
Like everyone else I am occasionally tempted to cut corners and postpone writing header comments, indexing clauses, and the like. But I censure myself because I know it means slower progress in the end.
No love for dynamic langs:
Why would anyone use an untyped or dynamically typed language? The argument “we’ll develop faster that way” makes no sense to me, either theoretically or practically
Demo
always have a working system
The only realiztic test is launch
One of the principles of design by contract, as earlier columns have said, is that any software element that has such a fundamental constraint should state it explicitly, as part of a mechanism present in the language.
Modelling the “real world” is a myth!
reality is in the eye of the beholder
software is at best only a model of a model of some part of reality
Allegory of the cave.
Too bad no one did. My life as an OOP developer would have been much nicer.
Describes EiffelBench
LoL
In environments supporting the most popular analysis methods, the little clouds and bubbles which seem to be the main selling points of these tools accurately reflect the vagueness surrounding the methods’ theoretical foundations and practical usefulness.
When quality is pursued, productivity follows
The law of excluded miracles:
it is amazing to see how far just stating what a module should do goes towards helping to ensure that it does it.
Cool fixity syntax decl. How to expand on this?
def _! <- |n|
factorial n.
5!
-- 120
def if_then_else_ <- |condition, then-part, else-part|
if condition:
,then-part
,else-part
if true then
42
36
-- 42
Lambda op syntax
Sequential source code with optional code blocks.
The first requirement in valid reasoning about a pro- gram is to know the properties of the elementary operations which it invokes
whoa!
he proven result of the first part of a program is identical with the precondition under which the second part of the program produces its intended result, then the whole program will produce the intended result, provided that the precondition of the first part is satisfied.
Explore further how currying reduces parens.
A list of fun languages to explore:
Describes something called “ribcage environments”.
I really need to re-read this for wzrdzkül.
Functional programs can often be transformed via algebra rather than some ad-hoc complex way.
Every paper cites Backus!
Awesome!
Whoa! In the first paragraph the author manages to offend Backus, McCarthy, Landis, etc. by calling them meta-programmers!
TODO: Explore further the idea of axioms.
Uses a variant of SASL
foldr and foldl have the same results when the function used is both associative and commutative.
(defn iota [t nxt stop y]
(take-while stop (iterate #(t (nxt %)) y)))
(iota identity inc #(< % 10) 1)
(def upto (fn [end start]
(iota identity inc #(< % end) start)))
(def downto (fn [end start]
(iota identity dec #(> % end) start)))
(upto 10 1)
(downto 10 20)
(defn to [start end]
(if (<= start end)
(upto end start)
(downto end start)))
(to 10 20)
(to 20 10)
(to 5 -5)
Fun fun fun.
In Defensive Programming every error and/or failure should be caught and handled by the software. There is no distinction between an error (a correctness problem) and a failure (a robustness problem). In DbC, there is a clear distinction between these two concepts. It is the responsibility of the programmer to fix all correctness errors.
{P} instructions {Q}
requires ensures
:pre :post
Summarized as:
Any execution of A started in a state satisfying P will terminate in a state satisfying Q.
Describes a language PROTOS-L that:
PROTOS-L is similar to DATALOG embedded in a typed logic programming language.
Provides:
Datalog v Prolog in a nutshell
(Pure) datalog may be seen as pure prolog without function symbols (of positive arity).
Combinator reduction for Haskell
Combinators used as an intermediate form for applicative languages and the machines that run them.
Describes the Small language (for symbolic algebra) - first-class function - call-by-need - robust error handling
Experience with the initial interpretive implementation of Small rapidly convinced us that any loss in expressive power that may result from removing imperative constructs from a language is more than balanced by the convenience of having normal order evaluation and higher order functions.
In its most primitive form combinatory logic is built up using just the two symbols S and K, which represent functions satisfying
K x y : x
S f g x = f x (g x)
and I would be:
I = S K K
Implements an eval and apply. Looks a lot like pg’s impl.
This paper is a good basis for a presentation.
This paper desccribes the Kent Recursive Calculator (KRC).
KRC is preceeded by SASL.
[1..]
is the way to express all natural numbers… is inc the default operation for the transition?
Computing science seems to suffer from the unwillingness to tell harsh truths.
With respect to COBOL you can really do only one of two things: fight the disease or pretend it does not exist.
good quote/ref for JoC
dynamically scoped variables turn out to be very useful when there is a need to influence the behavior of parts of a program with- out having to clutter the parameter lists of the functions called directly and/or indirectly.
which is Stallman’s thinking also
In those rare cases in which a lexically scoped global variable is actually needed, because it is important to be able to rebind it lexically, define-symbol-macro can be used to emulate it.
TODO: understand this more refs (1,18)
Common Lisp provides means to declare dynamically scoped local variables.
TODO: So does Clojure… possible blog post. L@@k when it is useful ref (3)
The decision for lexical or dynamic scope is to be made alongside the local definition of a function. (a la (binding ...))
(defn f [x] (println x))
(defn g [x] (f x))
(let [h (fn [x] (g x))]
(binding [f (fn [x] (print (inc x)))]
(h 5)))
; 6
Dynamically scoped function definitions is not enough. We also provide a way to refer to the previous definition of a function by way of an implicit local call-next-function definition.
something like:
(let [h (fn [x] (g x))]
(dflet [(f [x]
(call-next-fn (+ 1 x)))]
(h 5)))
This let’s the canonical AOP example occur
(defn f [x] (println x))
(dflet [(f [x] (println "entering f")
(call-next-fn)
(println "leaving f"))]
(f 5))
(defun f (x) (* x x))
translates into
(defvar *f* (lambda (x) (* x x)))
(defun f (&rest args) (apply *f* args))
Using a new defdynfun
(defmacro multidflet ((functions &body def) &body body)
‘(dflet ,(mapcar
(lambda (function)
‘(,function (&rest args) ,@def))
functions)
,@body))
Wow… has a lot of citations.
This paper considers two issues in the development of simulations: (i) narrowing the gap between model and program and (ii) using an embedded Domain Specific Language (DSL) rather than a General Purpose Language (GPL) or Simulation Programming Language (SPL).
No mention of implicits?
3rd or 4th reading – classic
Problems hosting fj on Java threads:
he java.lang.Thread class (as well as POSIX pthreads, upon which Java threads are often based) are suboptimal vehicles for supporting fork/join programs
Based on the design of Cilk.
Dequeues reduce contention when stealing.
Because the deque array is accessed by multiple threads, sometimes without full synchronization, yet individual Java array elements cannot be declared as volatile, each array element is actually a fixed reference to a little forwarding object maintaining a single volatile reference.
In many ways, modern GC facilities are perfect matches to fork/join frameworks: These programs can generate enormous numbers of tasks, nearly all of which quickly turn into garbage after they are executed.
Generational GC meshes well with parallelism.
Worker threads that consume the tasks they create are more efficient than stealing. Some tasks are more suited to locality than others.
Kinda boring
They (Mellish and Hardy 1982) critically advance that providing PROLOG with convenient connection to LISP is a complete solution.
The need for DSLs
One way to capture application-specific knowledge for a whole class of applications and simplify application development at the same time is to use a domain specific language (DSL). A DSL is a concise programming language with a syntax that is designed to naturally express the semantics of a narrow problem domain
The following is incorrect (or maybe just not specific enough)
Using DSLs naturally divides the application development process into two phases. First, a DSL developer designs a DSL for a specific domain. Then, a much larger number of domain experts make use of the DSL to develop applications.
This approach is a recipe for failure. The domain experts must be involved in the design of the DSL. The DSL developer is a fool in the domain by comparison. But they do say:
The ideal DSL developer would be a domain expert, a parallelism expert, and a language and compiler expert. Such developers are rare and so there is a need to simplify the process of developing DSLs for parallelism.
Uhhhhh. What? Maybe multiple people would work too. You think?
Argh! They list numerous properties of virtualizable languages (langs facilitating internal DSLs along the same footing as external DSLs):
No where do they mention robustness, error handling, etc. This is a huge problem for internal DSLs at the moment. Adding any kind of error reporting mucks up the implementation making it a huge mess. The problem is that you are effectively mapping the semantics of a domain onto the semantics of the host language forms. This is nice in some ways, but it is very very difficult to distinguish between a semantic error occurring at the host-level and one at the domain-level. This is the downfall of general-purpose languages as DSL hosts. What might work better is a special-purpose language meant for creating DSLs.
They mention:
Performance implies that programs in the embedded language must be amenable to extensive static and dynamic analysis, optimization, and code generation, just as programs in a stand-alone implementation would be.
But that phrasing is limiting. That’s not to say that it’s not powerful, just limiting. The term static-analysis is key.
Interesting…
Optimizing matrix operations is one of the classic examples of the use of C++ expression templates (48, 49) and is used by many systems such as Blitz++ (50), A++ (35, 36), and others.
A nice use-case for something like Clojail:
On the other hand, language embeddings in Lisp can be too seamless in that they do not distinguish between the embedded DSL and the hosting framework.
OK. So I was wrong. They never mentioned parentheses. I’m too cynical :p
implied-inference-ordered systems (iio)
Origins (an “of course they were” moment)
List com- prehensions have been introduced by David Turner in KRC, where they were called ZF-expressions
Miranda’s LC spec:
[ <expression> | <qualifier1> , . . . , <qualifiern> ]
Less concise Lisp comprehension:
(defmacro bind-map (shape effect list)
(let ((item (gensym)))
`(loop for ,item in ,list
collecting
(destructuring-bind ,shape ,item
(funcall (lambda () ,effect))))))
;;; when you have stupid builtins like PAIRLIS that return
;;; results of a certain shape (i.e. and association list instead
;;; of a proper list, you can use bind-map to get the shape you want)
;
;(bind-map (num . string)
; (list string num)
; (pairlis (list 1 2 3)
; (list "one" "two" "three")))
;
;=> (("three" 3) ("two" 2) ("one" 1))
;
;(bind-map (first second third)
; second
; (list (list 1 2 3)
; (list 4 5 6)
; (list 7 8 9)))
;
;=> (2 5 8)
;
;(bind-map (operator (type comment))
; comment
; '((+ (:binop "addition"))
; (- (:binop "subtraction"))
; (- (:unop "negation"))))
;
;=> ("addition" "subtraction" "negation")
Bigloo Scheme uses contracts
With one exception, higher-order languages have mostly ignored assertion-style contracts. The exception is Bigloo Scheme … These constraints are used to generate more efficient code when the compiler can prove they are correct and are turned into runtime checks when the compiler cannot prove them correct.
Think how this might be accomplished in Clojure
The gist of contracts
If x is not in the proper range, f’s caller is blamed for a contractual violation. Symmetrically, if f’s result is not in the proper range, the blame falls on f itself.
HOFs
higher-order functions complicate blame assignment.
Using Trammel
(defconstrainedfn sqrt
[x] [(>= x 0) => (>= % 0)]
(Math/sqrt x))
(defn bigger-than-zero? [n] (>= n 0))
(defconstrainedfn sqrt
[x] [bigger-than-zero? => bigger-than-zero?]
(Math/sqrt x))
The contract on sqrt can be strengthened by relating sqrt’s result to its argument.
Which can be done easily in Trammel:
(defconstrainedfn sqrt
[x] [bigger-than-zero? => bigger-than-zero? (<= (Math/abs (- x (* % %))) 0.01)]
(Math/sqrt x))
Types vs. Contracts
Although contracts can guarantee stronger properties than types about program execution, their guarantees hold only for particular program executions. In contrast, the type checker’s weaker guarantees hold for all program executions.
TODO: Is the wrap function useable in Trammel?
Module boundaries
Contracts are most effective at module boundaries, where they serve the programmer by improving the opportunities for modular rea- soning. That is, with well-written contracts, a programmer can study a single module in isolation when adding functionality or fixing defects.
A Flavor is analogous to a class.
combining specific implementations of different protocols under control of meta-protocols
Open system
Flavors provides more flexibility than other oop systems… … conventions become more important
http://planet.plt-scheme.org/package-source/jaymccarthy/datalog.plt
I wish Bracha would focus on the pluggable types rather than the Newspeak –fogus
Advantages of types: - machine-readable documentation - domain - early error detection - optimization
What are the flaws in these arguments? –fogus
Role of type system
The evaluation rules for typed λ calculi do not depend on their type rules. These calculi almost always share the same evalu- ation rules - those of the untyped λ calculus. The type system serves only to reject certain programs whose derivations might (or might not) “fail”.
The goal is to strive to separate the runtime from the type system.
It isn’t practical to add all these analyzers into a language, which is why most of them languish as exotic research projects. However, if the language provides a general framework for plugging in type systems, the situation can change. Programmers might benefit from a host of analyses that integrate cleanly into their code.
How to integrate multiple type systems? Clojure may have one answer:
One approach would leverage off of the growing support for user-defined annotations (often referred to as metadata) in programmming languages.
What about type inferencing?
A better engineering approach is to implement type inference as a separate tool, available in the IDE.
Classes are namespaces (modules)
One can define an entire class library or framework as a set of classes nested within an outer class, and then modify the library via inheritance, overriding classes defined within it. This is known as class hierarchy inheritance
In Newspeak, a top-level class constitutes a module definition. An instance of such a class is a module. Top level classes do not have access to their surrounding scope, and are inherently stateless.
Object capabilities
Implemented with Squeak Smalltalk
Future
D. Ungar and R. Smith. SELF: The power of simplicity. In Proc. of the ACM Conf. on Object-Oriented Programming, Systems, Languages and Applications, Oct. 1987.
H. Ossher and W. Harrison. Combination of inheritance hierarchies. In Pro- ceedings OOPSLA ’92, ACM SIGPLAN Notices, pages 25–40, Oct. 1992. Published as Proceedings OOPSLA ’92, ACM SIGPLAN Notices, volume 27, number 10.
M. S. Miller. Robust Composition: Towards a Unified Approach to Access Control and Concurrency Control. PhD thesis, Johns Hopkins University, Baltimore, Maryland, USA, May 2006.
B. B. Kristensen, O. L. Madsen, B. Møller-Pedersen, and K. Nygaard. The Beta Programming Language. In Research Directions in Object-Oriented Programming, pages 7–48. MIT Press, 1987.
what they thought Scheme would be…
We thought that Scheme would turn out to be the next in a long series of programming languages that had been designed at MIT over the course of 17 years. The principal themes of this series were complex data structures with automatic pattern matching, and com- plex control structures with automatic backtracking.
Conniver vs. ACTORS
Conniver made control points into first-class data, the actors model went to the logical extreme by making everything be first-class data.
their first attempt at an ACTORS language…
Using MacLisp as a working environment, we wrote a tiny Lisp interpreter and then added mechanisms for creating actors and sending messages.
lexical scope…
… starting with a lexically scoped dialect of Lisp, because that seemed necessary to model the way names could refer to acquaintances in PLASMA. Lexical scoping would allow actors and functions to be created by almost identical mechanisms.
eureka!
We concluded that actors and closures were effectively the same concept.
time and space (TODO: explore this notion further WRT Clojure, Lamport, Whitehead, Hewitt’s notion of “Cells”, etc.)
Synchronization and mutual exclusion are matters of time, not of space, and are not properly addressed by lexical scoping, which governs textual structures rather than the dynamics of execution.