General programming language question

Mon, 17 Feb 2003 02:35:05 +0900, Chris Pine nemo@hellotree.com pisze:

Is there a language where variables are first-class objects (in
which case I imagine assignment to be a normal function/method)?

Yes, several functional languages (SML, OCaml, Glasgow Haskell).
But the syntax is a bit ugly (or very ugly in Haskell).

In OCaml it looks like this (SML is similar):

First immutable variables or constants (they are called variables).
‘let x = 5 in …’ is similar to Ruby’s ‘X = 5; …’ - you can’t
change the value of x afterwards. It’s a binding of a value to a name,
shadowing any previous x.

Now mutable variables (called references). There is a type of
references which are one-element mutable cells. The function ‘ref’
creates a reference with a provided initial value. The operator
‘!’ reads a reference and the operator ‘:=’ changes the contents
of a reference.

Here is an example (artificial - nobody would write factorial this way):

let factorial n =
let result = ref 1 in
let i = ref 2 in
while !i <= n do
result := !result * !i;
i := !i + 1
done;
!result

Note that a name bound to a reference denotes the reference itself
(like any other name bound to an object), not its current contents.
You must explicitly dereference it when reading, and the lhs of :=
is the reference.

These operators aren’t even builtin. The primitive concept is a record
with some fields mutable, with operations for accessing and setting
record fields. A reference is a record with a single mutable field.

And well, my language has variables as first-class citizens but with
nicer syntax than OCaml :slight_smile:

The story could be explained thus. For now, every identifier begins
with ‘$’. An identifier denotes an object. Every object can be treated
as a function and applied to a sequence of objects, returning an
object. Application is written thus:
function argument1 argument2 argument3
except when there are no arguments:
function ()
where ‘function’ and ‘argumentN’ are arbitrary expressions.

Now, some syntactic sugar. ‘name’ is a shortcut for ‘$name ()’,
for any identifier. You can define a constant:
x = 5
which means
$x = makeConstant 5
where ‘makeConstant x’ returns an object which returns x when applied
to empty arguments. And you can define a variable:
var x := 5
which means
$x = makeVariable 5
where ‘makeVariable x’ produces an object which returns its current
contents when applied to empty arguments and sets it when applied to
one argument. The syntax
application := x
where ‘application’ is some function applied to some arguments means
the application with x appended as the last argument. Now, ‘name’
is an application (because it’s really ‘$name ()’), so ‘name := x’
means ‘$name x’.

So you can read the variable by writing its name, assign to it by
writing ‘name := newValue’, and pass it around with ‘$name’ (rarely
needed). ‘var x’ is the same as ‘var x := null’.

BTW, ‘obj.field’ is also an application, namely of the object denoted
by the expression obj to the symbol ‘field’. So such expression can
be assigned to, which applies the object to two arguments, a symbol
and a value, and the object may interpret it as setting a field
(or as something else).

‘dict@key’ or ‘arr@index’ is an application of the generic (@)
operator to 2 arguments. Such expression can be assigned to, which
applies (@) to 3 arguments and does the obvious thing when applicable.

You can write ‘$obj.field’ to make something similar to a reference to
a field. It is a function which accepts any arguments and just passes
them to obj, prepending the symbol ‘field’ as the first argument.
The function can be applied to 0 arguments (to read it) or to 1
argument (to write it), just like a first-class variable. Similarly
for ‘$dict@key’.

Some languages say that all activity is caused by sending messages to
objects. In my language it’s applying objects to arguments, and this
includes reading and writing mutable variables, unlike in Smalltalk.

···


__("< Marcin Kowalczyk
__/ qrczak@knm.org.pl
^^ Blog człowieka poczciwego.

Marcin ‘Qrczak’ Kowalczyk wrote:

Mon, 17 Feb 2003 02:35:05 +0900, Chris Pine nemo@hellotree.com pisze:

Is there a language where variables are first-class objects (in
which case I imagine assignment to be a normal function/method)?

Yes, several functional languages (SML, OCaml, Glasgow Haskell).
But the syntax is a bit ugly (or very ugly in Haskell).

First of all, I don’t agree that variables are first class
objects in any of the above languages.

Secondly: There are several drawbacks of using Haskell, but it
is definitively NOT the “ugly syntax”. I would
go so far to say that I have not seen a language with more
elegant syntax than Haskell (even compared to Ruby). Still
I prefer OCaml over Haskell for practical programming
for several reasons (inpurity, efficiency, compilation speed,
more mature libraries,module system), but I wish it had
Haskells syntax and type classes.

Best Regards, Christian

Mon, 17 Feb 2003 19:04:42 +0900, Christian Szegedy szegedy@nospam.or.uni-bonn.de pisze:

First of all, I don’t agree that variables are first class
objects in any of the above languages.

Mutable variables (SML & OCaml’s ref, Haskell’s IORef) are first-class.

Plain variables (named constants) aren’t, and it’s unnecessary,
since they are equivalent to their values.

Secondly: There are several drawbacks of using Haskell, but it is
definitively NOT the “ugly syntax”. I would go so far to say that
I have not seen a language with more elegant syntax than Haskell
(even compared to Ruby).

I agree, but not for mutable variables.

Haskell:

increment v = do
value ← readIORef v
writeIORef v (value + 1)

OCaml & SML:

let increment v = v := !v + 1

fun increment v = v := !v + 1

And in my language Kogut:

increment $v = v := v + 1

which is the same as

increment v = v (v() + 1)

···


__("< Marcin Kowalczyk
__/ qrczak@knm.org.pl
^^ Blog człowieka poczciwego.

First of all, I don’t agree that variables are first class
objects in any of the above languages.

···

----- Original Message -----
From: “Christian Szegedy” szegedy@nospam.or.uni-bonn.de


Yes… perhaps the confusion is my fault. I guess I should not have said
variables'... I meantbindings’.

Though, in thinking about this more, I think that good 'ol C has this;
they’re called pointers. And in C you can have pointers to pointers, but in
the “everything is a pointer” languages, I guess you really can’t have
pointers to pointers (or bindings and first-class objects). I think…

Anyway, I think I understand the pros and cons of that now. I guess you
could have some sort of mechanism for this in a language like Ruby… but I
don’t see why you’d want it.

Chris

Tue, 18 Feb 2003 00:29:50 +0900, Chris Pine nemo@hellotree.com pisze:

Yes… perhaps the confusion is my fault. I guess I should not
have said variables'... I meant bindings’.

Though, in thinking about this more, I think that good 'ol C has
this; they’re called pointers.

Ok, let me summarize. There are two approaches to bindings and variables:

  1. Immutable bindings, with mutable variables as separate first-class
    objects. This is usually the case in functional languages.

  2. Mutable bindings. This is more common.

Mutable bindings can be first-class in two ways: either the environment
of a scope (function, block etc.) is wrapped in an object which maps
local variable names to their current values, or individual variables
are objects which can be passed around. Or both.

For immutable bindings only the case of the whole environment is
interesting, because the immutable variable itself is equivalent to
its value.

Personally I don’t see the necessity of first-class environments.
Local variables are temporary and if you want to define many of them
in a loop, perhaps it’s better to put these objects in a dictionary
or array. It also makes optimization harder.

C, C++, Pascal and Perl are different than almost all other languages
in that their variables contain values instead of referring
to values existing elsewhere (in C, C++ and Pascal this model is the
only one possible because of lack of GC). In this model it’s necessary
to introduce pointers (sometimes called references), so you can also
refer to values stored in variables instead of making copies, or create
values which are not stored in variables.

In other languages you don’t need pointers to refer to objects,
so most languages omit them altogether.

···


__("< Marcin Kowalczyk
__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/