Hey /prog/, can your toy language do this? MODE P = PROC (P) P;
P i = (P x) P : x;
P v = (P x) P : v;
P k = (P x) P : ((P x, y) P: x)(x, );
P s = (P x) P : ((P x, y) P: ((P x, y, z) P: x(z)(y(z)))(x, y, ))(x, );
P succ = s(s(k(s))(k));
PROC side effect = (PROC VOID f) P : ((PROC VOID f, P x) P : (f; x))(f, );
PROC church = (INT n) P : (P f := k(i); TO n DO f := s(s(k(s))(k))(f) OD; f);
PROC int = (P f) INT : (INT n := 0; f((P x) P : (n +:= 1; i))(i); n);
OP + = (P x, y) P : ((P x, y, z) P : ((P x, y, z, w) P : x(z)(y(z)(w)))(x, y, z, ))(x, y, );
succ(church(10))(side effect(VOID : print(("Hello, world!", new line))))(i);
print(int(succ(church(100) + church(20))))
>>3
I like how he uses Lisp as an example for how languages shouldn't be, and two paragraphs later suggests that code should be stored in files as some data structure.
If we switch to using something other than text files, say XML or JSON or maybe a database, then many interesting things become possible. The IDE doesn't have to do a crappy job of divining the structure of your code. The structure is already saved. XML
What a faggot.
Name:
Anonymous2012-04-09 17:12
>>3
That "perfect language" already exists and it's called Lisp. Perfect if you're one of the IDE-wielding faggots, that is.
Some varieties of ALGOL 68 had modal declarations, similar to templates in C++. modallist = (modey) struct(refy a, reflist(y) next); proc apply = (modex)(reflist(x) a, proc(refx)void f)void;
Name:
Anonymous2012-04-09 20:46
My dubs are godtier
Name:
Anonymous2012-04-09 21:56
In Algol 68, a label is a parameterless procedure. PROC x = (PROC VOID x, INT n) INT : (n = 0|x; 0|n);
PROC func = VOID : print(("this should also be printed", new line));
x(label, 0);
print("should never be printed");
label:
print(("you should see this", new line));
x(func, 0);
x(VOID : print(("and this too", new line)), 0);
x(VOID : print(("but not this", new line)), 1)
C = toy language without variable-length multidimensional arrays [,][] INT two dimensional array of arrays = (((1,2,3),(4,5,6),(7,8,9)),
(( 1),( 2,3),(4,5,6)),
((5,6,7),(1,3,4),(9,8,2)));
print((two dimensional array of arrays, new line));
print(two dimensional array of arrays(2:3,1:2))
Name:
Anonymous2012-04-14 19:12
C = toy language without closures PROC counter generator = PROC INT : (
HEAP INT number := 0;
INT : number +:= 1);
PROC INT f = counter generator;
f;f;f;print(f)
>>23 solved with a good library >>24 solved with using structures to implement objects
but I'm not going to say that C isn't a toy language.
Name:
Anonymous2012-05-26 14:11
VOID = a mode (type) that signifies a lack of a value
EMPTY = the only value of VOID (used in a UNION like Nothing in Haskell)
NIL = the value of a reference that does not refer to any object
() = an empty array, called vacuum, which has an upper bound less than its lower bound
SKIP = an undefined value (like you would get in C if you don't initialize a variable)
undefined = a procedure that causes undefined behavior
ℵ = a prefix that creates a secret name to prevent external access to a structure field (like private)
>>28
answering my own question, I found out Algol 68 is garbage collected. confirmed for suckyness
Name:
Anonymous2012-05-26 22:12
Well... Algol was intended for standardizing the source code for algorithms published in academic journals after all, not segfaulting your enterprise kernals.
Name:
Anonymous2012-05-27 0:02
>>29
GC is great, manual memory allocation is shiSegmentation fault.
Name:
Anonymous2012-05-28 17:22
Can your language do this? # 11.10. Formula manipulation #
BEGIN
MODE FORM = UNION (REF CONST, REF VAR, REF TRIPLE, REF CALL);
MODE CONST = STRUCT (REAL value);
MODE VAR = STRUCT (STRING name, REAL value);
MODE TRIPLE = STRUCT (FORM left operand, INT operator, FORM right operand);
MODE FUNCTION = STRUCT (REF VAR bound var, FORM body);
MODE CALL = STRUCT (REF FUNCTION function name, FORM parameter);
INT plus=1, minus =2, times =3, by =4, to =5;
HEAP CONST zero, one; value OF zero := 0; value OF one := 1;
OP = = (FORM a, REF CONST b) BOOL: (a | (REF CONST ec): ec :=: b | FALSE);
OP + = (FORM a, b) FORM:
( a=zero | b |: b=zero | a | HEAP TRIPLE := (a, plus, b));
OP - = (FORM a, b) FORM: (b = zero | a | HEAP TRIPLE := (a, minus, b));
OP * = (FORM a, b)FORM: (a = zero OR b=zero | zero |: a=one | b |: b=one | a |
HEAP TRIPLE := (a, times, b));
OP / =(FORM a, b)FORM: (a = zero & (b =zero) | zero |: b=one | a |
HEAP TRIPLE := (a, by, b));
OP ^ = (FORM a, REF CONST b) FORM:
( a=one OR (b :=: zero) | one |: b :=: one | a | HEAP TRIPLE := (a, to, b));
PROC derivative of = (FORM e, # with respect to # REF VAR x) FORM:
CASE e IN
( REF CONST): zero,
( REF VAR ev): (ev :=: x | one | zero),
( REF TRIPLE et):
CASE FORM u = left operand OF et, v = right operand OF et;
FORM udash = derivative of(u, # with respect to # x),
vdash = derivative of(v, # with respect to # x);
operator OF et
IN
udash + vdash,
udash - vdash,
u * vdash + udash * v,
( udash -et * vdash) / v,
( v | (REF CONST ec): v * u ^ (HEAP CONST c;
value OF c := value OF ec - 1; c) * udash)
ESAC,
( REF CALL ef):
BEGIN REF FUNCTION f= function name OF ef;
FORM g = parameter OF ef; REF VAR y = bound var OF f;
HEAP FUNCTION fdash := (y, derivative of (body OF f, y));
( HEAP CALL := (fdash, g)) * derivative of(g, x)
END
ESAC;
PROC value of = (FORM e) REAL:
CASE e IN
( REF CONST ec): value OF ec,
( REF VAR ev): value OF ev,
( REF TRIPLE et):
CASE REAL u = value of (left operand OF et),
v = value of (right operand OF et);
operator OF et
IN u + v, u - v, u * v, u / v, exp (v * ln (u))
ESAC,
( REF CALL ef):
BEGIN REF FUNCTION f = function name OF ef;
value OF bound var OF f := value of (parameter OF ef);
value of (body OF f)
END
ESAC;
HEAP FORM f, g;
HEAP VAR a := ("a", SKIP), b := ("b", SKIP), x := ("x", SKIP);
# start here#
read ((value OF a, value OF b, value OF x));
f := a + x / (b + x);
g := (f+one) / (f-one);
print ((value OF a, value OF b, value OF x,
value of (derivative of(g, # with respect to # x))))
END # example OF formula manipulation #
Name:
Anonymous2012-05-28 18:18
Why don't any languages besides Algol 68 and Scheme and some other Lisp dialects make the syntax and usage for anonymous functions the same as for named functions?
In Algol 68, procedure denotations (literals) like (INT i)INT: 2 * i can be used anywhere a procedure of mode PROC(INT)INT can be used. You only need to give a value (procedures are values), variable or mode a name if it needs to refer to itself. A procedure denotation can be assigned or given a name with PROC double = (INT i)INT: 2 * i. Now you can write ((INT i)INT: 2 * i)(10) or double(10) and they will mean the same thing.
Most other languages have quirks and limitations with functions/procedures/methods compared to other data types. JavaScript and Perl don't use regular variable assignment syntax for creating named procedures. Ruby has blocks and lambdas and procs which are all different from methods created by def. C++ lambdas all have different types and can't be used as ordinary function pointers if they capture variables. Java needs inner classes to fake anonymous methods. Algol 68's syntax is more regular than any of those languages.
>>33
It's the most logical choice for Lisps-2. Consider this CL example: (defun foo (x) x)
(defun hot-foo-on-bar-action (foo bar) (foo bar))
If it worked as in Algol 68 then the rules for choosing the function to call would become slightly confusing.
That said, most other languages have no excuse.
Name:
Anonymous2012-05-29 12:42
JavaScript and Perl don't use regular variable assignment syntax for creating named procedures.
actually, they both do. but they also provide some syntactic sugar to make people unfamiliar with functional programming more comfortable.
Name:
Anonymous2012-06-03 21:19
In C++, there's the confusing pointers vs. references vs. const vs. lvalues vs. rvalues vs. literals distinction. C++11 adds rvalue references and constexpr. This all relates to how certain constructs in C++ must be constant expressions but others are allowed to be variable. C++ also passes values as mutable copies. If you want to alter the original object, you pass a reference or pointer.
Algol 68 is much more consistent. ALL of those are unified. All of these C++ concepts are expressed in terms of values (immutable) and ref values (mutable). In Algol 68, nothing needs to be a constant expression. References are values too, so there can be references to references to references and so on. In Algol 68, parameters are passed by value (identity declaration) and all values are immutable. (int i)int: i := 100 is a syntax error because ints are immutable values. It makes just as much sense to do 7 := 100. No copying is required whether a parameter is passed by value, by reference (ref) or by name (proc) because the original storage can always be used, whether it's mutable or immutable.
There are no lvalues or rvalues. The equivalent to an "lvalue" is a ref. If you do loc int i := 5 you create an anonymous local variable (ref int) and assign the value 5 to it. Any ref type can be used anywhere a variable can be used. If f is a proc (string) ref int, f("index") := 50 is valid Algol 68. The := operator dereferences until there is one more level of ref on the left side than on the right side.
Algol 68 has no "constant variables" because that's an oxymoron. There are either identity declarations, which give an identifier the value of an expression calculated at a particular point in time, like single assignment in functional languages, or assignations, which create a reference to mutable storage.
Since there's a GC, there are no pointers, only references. A reference to a reference can be made to refer to any existing mutable storage, just like a pointer can, but it's type safe and only refers to allocated memory.
The other use of pointers in C/C++, to access an array of values, is done using arrays or references to arrays. An array is a first-class data type, and is not related to ref at all ("orthogonal"), except that it adds mutability. Algol 68 arrays are much more flexible (no pun intended) than C arrays. []int(1,2,3,4,5,6,7)[@-3] is an array of integers with a lower bound of -3. arr[50:10] is the 10 element slice of array arr beginning at element 50. Multidimensional arrays can be sliced along any dimension. The built-in string type is defined as flex[0]char, a flexible array of characters. Bounds-checking prevents buffer overflows, preventing a huge number of bugs that are found in C/C++ programs.
>>38
Sorry, loc int i := 5 creates a local variable called i. loc int := 5 creates an anonymous local variable.
Name:
Anonymous2012-06-16 15:43
Algol 68 completely follows Tennent's Correspondence Principle, in a way that makes sense, with no arbitrary restrictions (even though it was designed before this principle was formulated). http://gafter.blogspot.com/2006/08/tennents-correspondence-principle-and.html Setting aside the technical details of Tennent's approach, the principle applies directly to the closure construct. A closure can be used to abstract over an expression or a statement. The principle dictates that an expression or statement, when wrapped in a closure and then immediately invoked, ought to have the same meaning as it did before being wrapped in a closure. Any change in semantics when wrapping code in a closure is likely a flaw in the language. http://blog.marcchung.com/2009/02/18/how-closures-behave-in-ruby.html http://techscursion.com/2012/02/tennent-correspondence-principle.html […] the underlying semantic notions for both parameter and definition mechanisms are simply expression evaluation (of an actual parameter or the right-hand side of a definition) and identifier binding (of a formal parameter or the left-hand side of a definition.) […] For any parameter mechanism, an analogous definition mechanism is possible, and vice versa. This is known as the principle of correspondence.
Some languages like Ruby and this Java lambda proposal make lambdas have incredibly strange effects, such as a return keyword returning from an outer method! By attempting to follow Tennent's Correspondence Principle, these languages make lambdas/closures different from ordinary (named/top-level) functions! In Algol 68, a function is a function, no matter where it comes from.
Algol 68 has no return, break, or continue. Instead, it has first-class labels and completers, which are labels that return values only if they are reached by a jump. Labels are lexically scoped. FOR i FROM 1 TO 100 DO
printf(($g(0)g$, i, ": "));
print((FOR j FROM 1 TO 10 DO
IF j = i THEN break FI;
printf(($g(0)" "$,j))
OD;FALSE EXIT break: TRUE));
IF i = 14 THEN break FI;
print(new line)
OD; break: ~
This EXIT keyword is a completer. If the inner loop exits normally, it returns FALSE, but if it exits through break it returns TRUE. PROC sum = (INT x)INT:(
INT ret val, PROC return = (INT i)VOID: (ret val := i; ret label);
INT i, sum := 0;
TO x DO read(i); (i < 0| return(sum)| sum +:= i) OD;
-1 EXIT ret label: ret val);
print(sum(5))
You can create a return statement in a similar way. If it loops more than x times, it returns -1. You could also do this by initializing ret val instead.
Algol 68 has what seemed to be an unusual restriction: declarations return no value, not even skip or void, so they must be followed by another statement. This makes perfect sense because it ensures lexical scoping! VOID: print("a"); # "a" is printed immediately #
# VOID: INT i := 60; # # Syntax error! #
VOID: (INT i := 60; ~); # Valid code #
You cannot declare an identifier that cannot be used anywhere. Here, i will immediately go out of scope. However, by wrapping it in parentheses (or begin/end), you create a new lexical scope. It still doesn't return a value, so you need at least ~ (a skip value), but it's valid code. VOID: (INT i; i := 60; print(i));
(INT i; i := 60; print(i))
These are the same because the procedure is immediately deprocedured. IF INT i := 5; i /= 0 THEN ~ # i is out of scope # FI;
PROC cond = BOOL: (INT i := 5; i /= 0);
IF cond THEN ~ # i is out of scope # FI
In some languages like C++, you can declare a variable inside of an if condition and use it in the then block. In Algol 68, you can't. This is because the IF and THEN clauses both have their own scopes. ((REF INT n)VOID: (n +:= 5; print(n)))(LOC INT := 15);
(REF INT n = LOC INT := 15; n +:= 5; print(n))
These are the same because a procedure parameter is equivalent to an identity declaration where the right-hand side is the actual parameter. Unlike C, where call-by-value creates a copy, Algol 68's call-by-value passes the value itself. When you say REF INT in a parameter, you are not passing an integer by reference, but passing the reference itself. In fact, INT i is an abbreviation for REF INT i = LOC INT.
Every computer language has arbitrary features, and most languages are in fact overloaded with them. A few, however, such as Lisp and Algol, are built around a kernel that seems as natural as a branch of mathematics. - Douglas R. Hofstadter
J. P. Baker: The Most Contrived Factorial Program BEGIN
PROC readint = INT: (INT i; read(i); i);
INT one=1, two=2, three=3, four=4, five=5, six=6,
seven=7, eight=8, nine=9, ten=10, eleven=11, twelve=12;
INT a=one;
PRIO ME=5, LOVE=7, MY=7, LORDS=7, LADIES=7,
PIPERS=7, DRUMMERS=7, MAIDS=7, SWANS=7, GEESE=7,
GOLD=7, COLLY=7, FRENCH=7, TURTLE=7, PARTRIDGE=6;
BOOL sent to=TRUE;
OP THE = (BOOL a)BOOL:a,
TWELFTH = (INT a)BOOL: a=twelve,
ELEVENTH = (INT a)BOOL: a=eleven,
TENTH = (INT a)BOOL: a=ten,
NINTH = (INT a)BOOL: a=nine,
EIGHTH = (INT a)BOOL: a=eight,
SEVENTH = (INT a)BOOL: a=seven,
SIXTH = (INT a)BOOL: a=six,
FIFTH = (INT a)BOOL: a=five,
FOURTH = (INT a)BOOL: a=four,
THIRD = (INT a)BOOL: a=three,
SECOND = (INT a)BOOL: a=two,
FIRST = (INT a)BOOL: a=one;
OP ME = (BOOL a, INT b)VOID: (IF a THEN print(b) FI),
LOVE = (BOOL a, b)BOOL: (IF a THEN b ELSE FALSE FI),
MY = (BOOL a, b)BOOL: a LOVE b,
AND = (INT a)INT: a;
MODE DATE = STRUCT(INT day, month);
DATE christmas := (25, 12);
OP LORDS = (INT a, b)INT: a*b,
LADIES = (INT a, b)INT: a*b,
PIPERS = (INT a, b)INT: a*b,
DRUMMERS = (INT a, b)INT: a*b,
MAIDS = (INT a, b)INT: a*b,
SWANS = (INT a, b)INT: a*b,
GEESE = (INT a, b)INT: a*b,
GOLD = (INT a, b)INT: a*b,
COLLY = (INT a, b)INT: a*b,
FRENCH = (INT a, b)INT: a*b,
TURTLE = (INT a, b)INT: a*b;
OP LEAPING = (INT a)INT: a,
DANCING = (INT a)INT: a,
PIPING = (INT a)INT: a,
DRUMMING = (INT a)INT: a,
MILKING = (INT a)INT: a,
SWIMMING = (INT a)INT: a,
LAYING = (INT a)INT: a,
RINGS = (INT a)INT: a,
BIRDS = (INT a)INT: a,
HENS = (INT a)INT: a,
DOVES = (INT a)INT: a;
OP PARTRIDGE = (INT a, b)INT: a+b;
INT in a pear tree = 0;
print("Factorial of ");
print(day OF christmas := readint);
print(" is ");
IF day OF christmas > 12 THEN
print("too big for this program.");
stop
FI;
# Now we are ready.. #
THE FIRST day OF christmas MY TRUE LOVE sent to ME
a PARTRIDGE in a pear tree;
THE SECOND day OF christmas MY TRUE LOVE sent to ME
two TURTLE DOVES AND
a PARTRIDGE in a pear tree;
THE THIRD day OF christmas MY TRUE LOVE sent to ME
three FRENCH HENS
two TURTLE DOVES AND
a PARTRIDGE in a pear tree;
THE FOURTH day OF christmas MY TRUE LOVE sent to ME
four COLLY BIRDS
three FRENCH HENS
two TURTLE DOVES AND
a PARTRIDGE in a pear tree;
THE FIFTH day OF christmas MY TRUE LOVE sent to ME
five GOLD RINGS
four COLLY BIRDS
three FRENCH HENS
two TURTLE DOVES AND
a PARTRIDGE in a pear tree;
THE SIXTH day OF christmas MY TRUE LOVE sent to ME
six GEESE LAYING
five GOLD RINGS
four COLLY BIRDS
three FRENCH HENS
two TURTLE DOVES AND
a PARTRIDGE in a pear tree;
THE SEVENTH day OF christmas MY TRUE LOVE sent to ME
seven SWANS SWIMMING
six GEESE LAYING
five GOLD RINGS
four COLLY BIRDS
three FRENCH HENS
two TURTLE DOVES AND
a PARTRIDGE in a pear tree;
THE EIGHTH day OF christmas MY TRUE LOVE sent to ME
eight MAIDS MILKING
seven SWANS SWIMMING
six GEESE LAYING
five GOLD RINGS
four COLLY BIRDS
three FRENCH HENS
two TURTLE DOVES AND
a PARTRIDGE in a pear tree;
THE NINTH day OF christmas MY TRUE LOVE sent to ME
nine DRUMMERS DRUMMING
eight MAIDS MILKING
seven SWANS SWIMMING
six GEESE LAYING
five GOLD RINGS
four COLLY BIRDS
three FRENCH HENS
two TURTLE DOVES AND
a PARTRIDGE in a pear tree;
THE TENTH day OF christmas MY TRUE LOVE sent to ME
ten PIPERS PIPING
nine DRUMMERS DRUMMING
eight MAIDS MILKING
seven SWANS SWIMMING
six GEESE LAYING
five GOLD RINGS
four COLLY BIRDS
three FRENCH HENS
two TURTLE DOVES AND
a PARTRIDGE in a pear tree;
THE ELEVENTH day OF christmas MY TRUE LOVE sent to ME
eleven LADIES DANCING
ten PIPERS PIPING
nine DRUMMERS DRUMMING
eight MAIDS MILKING
seven SWANS SWIMMING
six GEESE LAYING
five GOLD RINGS
four COLLY BIRDS
three FRENCH HENS
two TURTLE DOVES AND
a PARTRIDGE in a pear tree;
THE TWELFTH day OF christmas MY TRUE LOVE sent to ME
twelve LORDS LEAPING
eleven LADIES DANCING
ten PIPERS PIPING
nine DRUMMERS DRUMMING
eight MAIDS MILKING
seven SWANS SWIMMING
six GEESE LAYING
five GOLD RINGS
four COLLY BIRDS
three FRENCH HENS
two TURTLE DOVES AND
a PARTRIDGE in a pear tree
END
Name:
Anonymous2012-08-01 23:31
``[Algol 60] is a language so far ahead of its time, that it was not only an improvement on its predecessors, but also on nearly all its successors.''
``Algol 68 would have been an improvement over most of its successors, had it had any.''