function factorial(n) if n == 0 then return 1 end return n * factorial(n - 1) end - Lua factorial = (n) { if {n == 0} { 1! } n * { factorial { n - 1 } } } Hmm, using ! as soft return won't work. There needs to be a hard return and a soft return both. Sigh. ! seems the harder, so return would be soft. Still not sure about generators and hashtables. factorial = (n) { myset = { Set "p" "q" "r" } hash = { Hash p = q; q = p } } ~@aoprkaokrg@ printdoc = { say ~ Hello there. This is documentation Ain't it swell? say ~"Hello world!" } Oh, , could be a synonym for set! myset = { "p", "q", "r" } Might have to have a syntax for hash, sadly. Hash[ atom = atom, atom = atom ] It's like a table in Lua. function Point(x,y) -- "Point" object constructor return {x = x, y = y} -- Creates and returns a new object (table) end array = { Point(10,20), Point(30,40), Point(50,60) } -- Creates array of points print( array[2].y ) -- Prints 40 point = (x y) { Hash("x" = x, "y" = y) } array = (point 10 20; point 30 40; point 50 60) say { get { array member 2 } "y" } path = { strim env.PATH_INFO "/" } for { if {/something/ match arg} { out arg } } @@ Duck typing. :cat something.txt Hmm. numbers = [1, 2, 3, 4, 5] powers_of_two = [2**n for n in numbers] numbers = (1 2 3 4 5) powersOfTwo = { list { 2 ** arg } numbers } def qsort(L): if L == []: return [] pivot = L[0] return qsort([x for x in L[1:] if x < pivot]) + [pivot] + \ qsort([y for y in L[1:] if y >= pivot]) qsort = (L) { if {L == ()} { ()! } pivot = { L member 0 } { qsort { list arg {L from 1} {arg < pivot} } } + { list pivot } + \ { qsort { list arg {L from 1} {arg >= pivot} } } I miss Python's slice and accessor syntax. dispatch = { "something": something, "blargh": "blargh } dispatch[name]() dispatch = { Hash( "something" = something, "blargh" = blargh )} { get dispatch name } dispatch [name] If we allow coordination with two args, [name] could be a kind of object that gets an index. dispatch[name] array[1:] Anyway, we should probably have a confused listdict type. "Table" would be fine as a name actually. That would imply that all of these are valid: (1 2 3 4 5) ("first" = 1, "second" = 2, "third" = 3) It is a special syntax, so I guess that's allowable. Note that if [atom] is the syntax, [:5] will pass through the executable variable :5, so it'll have to be name based. This is becoming a rather peculiar feature of this language: the syntax is really quite context dependent, but all the objects are the same. So some special datatype syntax has constituent atoms, some doesn't. dispatch = ( "something" = something "blargh" = blargh ) dispatch[name] Nice trick: dispatch[/some/] Returns a table: (something). qsort = (L) { if {L == ()} { ()! } pivot = { L member 0 } { qsort { filter {arg < pivot} {L[1:]} } } + (pivot) + \ { qsort { filter {arg >= pivot} {L[1:]} } } } That's a bit dorky. Perhaps an operator? Again were it not for the URI type... while {f readline} { print arg } @@ TimBL's warning about search paths. numbers = { $i = 1; yield $i; $i++ } for {numbers} { {arg > 100} break say arg } write = (f *args) { py f.write { join "" args } } out = (*args) { write stdout args } say = (*args) { out { args + ("\n") } } Or, if Table + String does the right thing... say = (*args) { out { args + "\n" } } All built-in functions might have to watch for the first arg being = and dispatch accordingly. write = (f *args) { ... } -> write op.equals (f op.star args) { op.ellipsis } Or op.yadda. Anyway, that would exec write. This might be somewhere where Perl6's argspec conditions help... write = (f {f != op.equals} *args) { ... } So if the arcspec fails, coordinate? This is kinda nutty, but on the other hand the simple hackable semantics is rather nice. And I was leading up to this anyway since "readline" is kinda like a ... it's extensible in some strange way, and I guess there's some sort of duck typing thing going on in here. So I might want a function name to behave differently with different things. read = (arg {arg a File}) { ... } read = (arg {arg a EmailClient}) { ... } Which is basically strict typing. Huh... { ... } is basically a Table containing a single yadda. What makes it different from a Table? That'll come out in the implementation. Coordination really is one wacky bastard of a feature! # Impelementation main = (argv) { output = { join " " ("Hello" "world!") } say output } script main Each block is to be a Table itself, with various variables. So the above should compile to something like: Table(Block) { "prog": Table(Variables) { "script": script } 0: Table(Command) { 0: Variable("main"), 1: Variable("@op.equals"), 2: Table(Argspec) { 0: Variable("argv") }, 3: Table(Block) { "parent": parent(), "prog": self["parent"].prog, 0: Table(Command) { 0: Variable("output"), 1: Variable("@op.equals"), 2: Table(Block) { "parent": parent(), "prog": self["parent"].prog, 0: Variable("join"), 1: String(" "), 2: Table() { 0: String("Hello"), 1: String("world!") } } }, 1: Table(Command) { 0: Variable("say"), 1: Variable("output") } } }, 1: Table(Command) { 0: say, 1: Variable("output") } } Oh, polysemic operators. Kind? Type? Species? program = { "kind": "Closure", "prog": { "kind": "Variables", "script": script } 0: { "kind": "Command", 0: Variable("main"), 1: Variable("@op.equals"), 2: { "kind": "Argspec", 0: Variable("argv") }, 3: { "kind": "Closure", "parent": parent(), "prog": self["parent"].prog, 0: { "kind": "Command", 0: Variable("output"), 1: Variable("@op.equals"), 2: { "kind": "Closure", "parent": parent(), "prog": self["parent"].prog, 0: Variable("join"), 1: String(" "), 2: { 0: String("Hello"), 1: String("world!") } } }, 1: { "kind": "Command", 0: Variable("say"), 1: Variable("output") } } }, 1: { "kind": "Command", 0: say, 1: Variable("output") } } Try to avoid establishing silly conventions. -- Sean B. Palmer, inamidst.com