While we're throwing out wild and whacky ideas, here's one I've been
mulling for a few days.

You know how the lisp evaluator reads a list, evals all the elements,
passes the cdr as arguments to the car? Forget all that. New rules:

a) Adjacent expressions = function application.

  factorial 5 => 120
  ++ 3 => 4

Corollary: The function doesn't have to come first.

  5 factorial => 120
  3 ++ => 4

b) What if a function needs 2 args? Or 3? Curry.

  + 1 2 => ((+ 1) 2) => 3

Now we suddenly have infix for free, thanks to above corollary.

  1 + 2 => ((1 +) 2) => 3

(Still no precedence though. Sorry, math guys :)

  1 + 2 * 3 => ((((1 +) 2) *) 3)

c) You don't have to repeatedly curry functions, you can just pass in a list.

  +(1, 2) => 3
  cons(1, 2) => (1 . 2)

As a corollary, parentheses are just for grouping. They never mean a
function call.

  (+ 1 2) <=> ((+ 1 2))

And that's it! I think this s-expression language would admit
convenient macros. And I'm not sure if you need quote anymore..

===

I've thought about a couple of additional frills you could add to this language:

A. You could interpret this programming model using an accumulator.

  > + 1 2
  ; + => store + in accumulator
  ; 1 => combine + and 1, store a curried function in accumulator
  ; 2 => combine curried function and 2, store 3 in accumulator
  3 ; finally print 3

The combination of currying and an accumulator seems to do what a
stack does in forth or factor. Instead of functions picking up
arguments from a stack, there's a *queue* of arguments trotting into a
function's mouth. When the function's done eating all the args it
needs it closes its mouth, digests, excretes a result to the
accumulator, and vanishes.

B. If you have rules for how values of various types coerce to
functions you can get array and hash dereference. Just treat all kinds
of brackets as groupers.

  array[2, 3] => (array 2 3) => ((array 2) 3)
  hash{key} => (hash key)

You can also coerce booleans to functions and turn 'if' into a
single-arg function.

  if (x < 3) {
    print "haha";
    34;
  }

  ; =>  (if (x < 3)) { .. }

  ; => true { .. }

  ; => eval-all { print "haha"; 34 }

Compare this with smalltalk: (3 < 4) :iftrue [ print "haha"; 34; ]
(I suck at smalltalk, so this has a negligible chance of being correct syntax.)

One assumption I'm making in this code fragment is that semi-colons
are delimiters. Just like all kinds of brackets behave the same,
semi-colons and commas are delimiters and behave the same, serving
only to separate elements of a list or array.

  { a; b; c; d } <=> (a, b, c, d) <=> [a, b, c, d]

This flexibility allows us to add the illusion of syntax without
giving up s-expressions and macros.

C. You can make parens optional like in ruby:

  f a, b, c => f(a, b, c)

All of this suggests to me that all talk of lisp 'permitting macros'
because it is 'homoiconic' is a canard. You can build parse trees and
macros for any syntax. It's just that the people who want such syntax
haven't cottoned on to the power of macros. Or they haven't realized
the value of optional syntax, or of redundant syntax where multiple
tokens mean exactly the same thing.

I'm not sure I would use all this syntax, but it might be worth
turning this idea into a language, just as a proof of concept. The
name for this language is blazingly self-evident:

Blub.

PS: Either this is broken in some fundamental way, or somebody's
already discovered this before. Please educate me.

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Readable-discuss mailing list
Readable-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-discuss

Reply via email to