# Q: functional/equational language, smells a little of Python

Discussion in 'Python' started by John J. Lee, Jun 4, 2005.

1. ### John J. LeeGuest

Saw this on LWN:

http://q-lang.sourceforge.net/

Looks interesting, and reminiscent of symbolic algebra systems like
Mathematica. Also, the website mentions dynamic typing and "Batteries
Included", which made me think of Python. Damned silly name, though

Anybody here used it?

Snippet from the FAQ:

2. Yet another "Haskell for the poor"?

Not quite. Even though the syntax and some of the stuff in the
standard library looks superficially similar, Q is different in a
number of ways:

* First and foremost, Q is an equational rather than just a
functional language, meaning that it is based on general term
rewriting instead of the lambda calculus (which is just one, and
very special, rewriting system). In particular, Q has no a
priori distinction between "constructors" and "defined" function
symbols, and argument patterns are not restricted to
"constructor terms". This allows you to have symbolic evaluation
rules like the following distributivity rule: X*(Y+Z) =
X*Y+X*Z. Such rules are not allowed in ML and Haskell because
they violate the "constructor discipline". Moreover, the Q
interpreter also happily reduces expressions involving
variables, so that you can try your definitions with symbolic
inputs (e.g., map F [X,Y] will evaluate to [F X,F Y]), which is
quite useful for debugging purposes.

* While other functional languages are either "eager" or "lazy", Q
tries to give you the best of both worlds: It uses eager
(call-by-value) evaluation by default (which lends itself to an
efficient implementation), but also allows you to define your
own special forms, which can be used to implement both
call-by-name functions and lazy data constructors. Using special
forms you can also define your own "meta functions" which
manipulate arbitrary (not necessarily irreducible) expressions
as literal terms. This gives you full control over the reduction
strategy, where this is desired, as well as a kind of "macros"
and "self-modifying programs", since constructs like lambda
abstractions can be analyzed, transformed and constructed in
many ways before they are actually evaluated.

* Q uses dynamic typing. This has become a rare feature in
contemporary functional languages, which usually employ a
Hindley/Milner type system which offers more safety at the
expense of restricting polymorphism. Q gives you back the
flexibility of good old Lisp-style ad-hoc polymorphism and even
allows you to extend the definition of existing operations
(including built-in functions and operators) to your own data
types. Moreover, Q has a Smalltalk-like object-oriented type
system which supports data encapsulation and (single)
inheritance. This makes it possible to manage complex,
polymorphic data with ease.

* Q takes the pragmatic route in that it provides (monad-free)
imperative programming features such as imperative I/O and
mutable data cells, similar to the corresponding facilities in
ML. While one may argue about these, they certainly make life
easier when programming complex I/O stuff such as graphical user
interfaces.

* Last but not least, the Q programming system comes with
batteries included. There are quite a few add-on modules
interfacing to third-party libraries which, while not as
comprehensive as the facilities provided by traditional
scripting languages like Perl and Python, allow you to tackle
most practical programming problems with ease. In particular,
multimedia and computer music is an area where Q shines,
providing facilities to handle graphics, digital audio and MIDI
in a convenient and efficient manner (efficient enough for soft
realtime applications), which go well beyond what is currently
being offered for other functional languages.

Some of Q's flexibility comes at a price. In particular, Q's symbolic
evaluation capabilities as a term rewriting language dictate that the
language is essentially exception-free. This means that an
"ill-formed" expression (such as "division by zero" or, more
generally, the application of a function to data for which there is no
corresponding definition) does not, by default, raise an exception,
but instead the expression is already in "normal form", i.e., it
evaluates to itself. As a remedy, Q provides facilities to add
explicit error rules which raise exceptions, and to handle exceptions
in a suitable manner. Another limitation is that Q does not allow you
to have arbitrary local definitions in the style of Haskell and ML's
"let" and "where" clauses. In Q, "where" clauses are limited to
variable definitions (similar to Haskell's pattern bindings), but
local rewriting rules are not supported as they would wreak havoc on
the term rewriting semantics.

You will also notice that Q lacks most of the syntactic sugar found in
Haskell. This is partly due to my laziness, but it also keeps the
language and the core system simple. Using Q's symbolic processing
capabilities, the usual bits like lambda abstractions, pattern
matching conditionals and list comprehensions can easily be written in
Q itself (although this does not offer quite the same performance as
when they are provided as builtins, of course).

John

John J. Lee, Jun 4, 2005

2. ### Kay SchluehrGuest

John J. Lee wrote:
> Saw this on LWN:
>
> http://q-lang.sourceforge.net/
>
>
> Looks interesting, and reminiscent of symbolic algebra systems like
> Mathematica. Also, the website mentions dynamic typing and "Batteries
> Included", which made me think of Python. Damned silly name, though
>
> Anybody here used it?
>
> Snippet from the FAQ:
>
>
> 2. Yet another "Haskell for the poor"?
>
> Not quite. Even though the syntax and some of the stuff in the
> standard library looks superficially similar, Q is different in a
> number of ways:
>
> * First and foremost, Q is an equational rather than just a
> functional language, meaning that it is based on general term
> rewriting instead of the lambda calculus (which is just one, and
> very special, rewriting system). In particular, Q has no a
> priori distinction between "constructors" and "defined" function
> symbols, and argument patterns are not restricted to
> "constructor terms". This allows you to have symbolic evaluation
> rules like the following distributivity rule: X*(Y+Z) =
> X*Y+X*Z. Such rules are not allowed in ML and Haskell because
> they violate the "constructor discipline". Moreover, the Q
> interpreter also happily reduces expressions involving
> variables, so that you can try your definitions with symbolic
> inputs (e.g., map F [X,Y] will evaluate to [F X,F Y]), which is
> quite useful for debugging purposes.
>
> * While other functional languages are either "eager" or "lazy", Q
> tries to give you the best of both worlds: It uses eager
> (call-by-value) evaluation by default (which lends itself to an
> efficient implementation), but also allows you to define your
> own special forms, which can be used to implement both
> call-by-name functions and lazy data constructors. Using special
> forms you can also define your own "meta functions" which
> manipulate arbitrary (not necessarily irreducible) expressions
> as literal terms. This gives you full control over the reduction
> strategy, where this is desired, as well as a kind of "macros"
> and "self-modifying programs", since constructs like lambda
> abstractions can be analyzed, transformed and constructed in
> many ways before they are actually evaluated.
>
> * Q uses dynamic typing. This has become a rare feature in
> contemporary functional languages, which usually employ a
> Hindley/Milner type system which offers more safety at the
> expense of restricting polymorphism. Q gives you back the
> flexibility of good old Lisp-style ad-hoc polymorphism and even
> allows you to extend the definition of existing operations
> (including built-in functions and operators) to your own data
> types. Moreover, Q has a Smalltalk-like object-oriented type
> system which supports data encapsulation and (single)
> inheritance. This makes it possible to manage complex,
> polymorphic data with ease.
>
> * Q takes the pragmatic route in that it provides (monad-free)
> imperative programming features such as imperative I/O and
> mutable data cells, similar to the corresponding facilities in
> ML. While one may argue about these, they certainly make life
> easier when programming complex I/O stuff such as graphical user
> interfaces.
>
> * Last but not least, the Q programming system comes with
> batteries included. There are quite a few add-on modules
> interfacing to third-party libraries which, while not as
> comprehensive as the facilities provided by traditional
> scripting languages like Perl and Python, allow you to tackle
> most practical programming problems with ease. In particular,
> multimedia and computer music is an area where Q shines,
> providing facilities to handle graphics, digital audio and MIDI
> in a convenient and efficient manner (efficient enough for soft
> realtime applications), which go well beyond what is currently
> being offered for other functional languages.
>
>
> Some of Q's flexibility comes at a price. In particular, Q's symbolic
> evaluation capabilities as a term rewriting language dictate that the
> language is essentially exception-free. This means that an
> "ill-formed" expression (such as "division by zero" or, more
> generally, the application of a function to data for which there is no
> corresponding definition) does not, by default, raise an exception,
> but instead the expression is already in "normal form", i.e., it
> evaluates to itself. As a remedy, Q provides facilities to add
> explicit error rules which raise exceptions, and to handle exceptions
> in a suitable manner. Another limitation is that Q does not allow you
> to have arbitrary local definitions in the style of Haskell and ML's
> "let" and "where" clauses. In Q, "where" clauses are limited to
> variable definitions (similar to Haskell's pattern bindings), but
> local rewriting rules are not supported as they would wreak havoc on
> the term rewriting semantics.
>
> You will also notice that Q lacks most of the syntactic sugar found in
> Haskell. This is partly due to my laziness, but it also keeps the
> language and the core system simple. Using Q's symbolic processing
> capabilities, the usual bits like lambda abstractions, pattern
> matching conditionals and list comprehensions can easily be written in
> Q itself (although this does not offer quite the same performance as
> when they are provided as builtins, of course).
>
>
> John

I'm curious why do you think that it "smells like Python"? Because of
"batteries included"? Are dotNET and Java Python-like because they come
up with a fast object library?

Personally I think that time has passed for functional languages except
for academic studies. Features like term rewriting are interesting per
se but I believe that they can be implemented on top of dynamic OO
languages like Python with some effort too. My expectation of future
Computer Algebra Systems ( CAS ) is that they provide models of
mathematical objects like algebras, sets, spaces, manifolds,
number-fields etc. that can be refined using inheritance and can be
adapted dynamically. Despite the majority of people working in CA I
think that OO is much more the way contemporary mathematicians think
about their stuff than the FP toolbox approach. What I'm missing is a
kind of domain specific syntax, e.g. a <ket|bra> syntax for working
with states in quantum mechanics. But that's out of the scope of
current Python.

Regards,
Kay

Kay Schluehr, Jun 5, 2005

3. ### John J. LeeGuest

"Kay Schluehr" <> writes:
[...]
> I'm curious why do you think that it "smells like Python"? Because of
> "batteries included"?

Partly that and the mention of dynamic typing, plus harder-to-pin down
things.

I didn't mean to say that it was close kin to Python, just that on
first impression it has some similarities.

> Are dotNET and Java Python-like because they come
> up with a fast object library?

[...]

What's a fast object library?

John

John J. Lee, Jun 5, 2005
4. ### Robin BeckerGuest

John J. Lee wrote:
.....
>
> What's a fast object library?
>

ferrarilib

--
Robin Becker

Robin Becker, Jun 5, 2005
5. ### Kay SchluehrGuest

John J. Lee wrote:
> "Kay Schluehr" <> writes:
> [...]
> > I'm curious why do you think that it "smells like Python"? Because of
> > "batteries included"?

>
> Partly that and the mention of dynamic typing, plus harder-to-pin down
> things.
>
> I didn't mean to say that it was close kin to Python, just that on
> first impression it has some similarities.

O.K.

>
> > Are dotNET and Java Python-like because they come
> > up with a fast object library?

> [...]
>
> What's a fast object library?

Sorry. 'Fast' was nonsense.

Kay

Kay Schluehr, Jun 5, 2005