|
@@ -0,0 +1,108 @@
|
|
|
+RAKU is a scripting language that resembles Engish somewhat.
|
|
|
+However it is a stealth lisp with smalltalk like semantics.
|
|
|
+
|
|
|
+In Lisp you would say (function1 arg1 (function2 arg2))
|
|
|
+In C you would write function1(arg1, function2(arg2));
|
|
|
+In Raku you will write function1 arg1 be function2 arg2 so
|
|
|
+
|
|
|
+
|
|
|
+attack the greater green gorgon with the large axe
|
|
|
+
|
|
|
+# Core problem: in most languages, arguments of a function are not only
|
|
|
+# delimited, but also the start and end of the function call
|
|
|
+# are indicated somehow, so that calling several functions in one statement
|
|
|
+# is possible. Similarly for message passing.
|
|
|
+# C-like:
|
|
|
+# foo(a, b, c)
|
|
|
+# foo(a, bar(b , c) ,d ,e)
|
|
|
+# Lisp-like:
|
|
|
+# (foo a b c)
|
|
|
+# (foo a (bar b c) d e)
|
|
|
+# What I'd like for Raku is drop the outer ()
|
|
|
+# foo a (bar b c) d e
|
|
|
+# Here the newline at the end, or the . make is clear the statement is finished.
|
|
|
+# However, calling functions still requires a special delimiter.
|
|
|
+# Unless if the parser knows that foo and bar are functions/methods/verbs.
|
|
|
+# Then it can distinguish between foo and bar and a b c d e.
|
|
|
+# But then it still can't see where an inner call ends and the top level
|
|
|
+# one begins: VERB NOUN PREP VERB NOUN PREP NOUN EOL ->
|
|
|
+# is this VERB(NOUN , VERB(NOUN, NOUN)) or VERB(NOUN , VERB(NOUN), NOUN)?
|
|
|
+# Without an end-of call delimiter the parser cannot know.
|
|
|
+# For the simple case of VERB NOUN PERP NOUN EOL
|
|
|
+# the EOL acts as the "end of call" marker, but it can't be used twice.
|
|
|
+#
|
|
|
+# I checked Inform 7 but it's a huge language with many unnecessary
|
|
|
+# complexities. It's simpler to solve the delimiter problem by using short words.
|
|
|
+#
|
|
|
+# an as at ax be by do go if of in is it me no of or ox so to up us we
|
|
|
+#
|
|
|
+#
|
|
|
+# set foobar to be add 10 to 10 so
|
|
|
+# set foobar to tally add 10 to 10 end
|
|
|
+# for i from 0 to be size foo so then do
|
|
|
+#
|
|
|
+# end
|
|
|
+# do / sub / block ... so / end / done -> block
|
|
|
+# be / run / call ... so / end / done -> sub-call, parenthesis
|
|
|
+# list / array ... so / end / done -> array/list value
|
|
|
+# act / define WORD [NAME [PREP NAME] BLOCK-> method definition on first NAME, which should be a type or instance. If none is given, "me" is used.
|
|
|
+# use NAME -> variable declaration takes values of arguments give to block if any.
|
|
|
+# nil / nothing / none / -> nil value
|
|
|
+# true / false / yes / no -> boolean value
|
|
|
+# return -> method return
|
|
|
+# yield -> block return
|
|
|
+
|
|
|
+This is unambiguous in IO or Potion:
|
|
|
+
|
|
|
+OBJECT METHOD1(ARG1_1, ARG1_2, ...) METHOD2(ARG2_1, ...) METHOD3 EOL
|
|
|
+
|
|
|
+# Inversed, apart from the parameters this becomes:
|
|
|
+METHOD3 METHOD2(ARG_2_1, ...) METHOD1(ARG1_1, ARG1_2, ....) OBJECT
|
|
|
+#
|
|
|
+# So io/potion ish
|
|
|
+Bob name append(" and ", Jane name) println
|
|
|
+# Would invert to
|
|
|
+println append(" and ", name Jane ) name Bob
|
|
|
+# now substitute the non-words with words
|
|
|
+println append of " and " with name Jane end name Bob
|
|
|
+# or if we use and for method chaining
|
|
|
+println and append " and " with name Jane and name Bob
|
|
|
+
|
|
|
+# So io/potion ish
|
|
|
+Bob hp decrease(Bob hp times(10) divide(Bob hpmax))
|
|
|
+# Would invert to
|
|
|
+decrease(divide(hpmax Bob) times(10) hp Bob) hp Bob
|
|
|
+# now substitute the non-words with words
|
|
|
+decrease tally divide of hpmax Bob end times tally 10 end hp Bob end hp Bob
|
|
|
+# or if we use and for method chaining
|
|
|
+decrease tally divide tally hpmax Bob end and times tally 10 end and hp Bob end and hp Bob
|
|
|
+
|
|
|
+# Conclusion, mere complete inversion is undesirable because the sequence
|
|
|
+# becomes unclear, what happens last is set first.
|
|
|
+# What is desirable is that like in English the verb comes before the object,
|
|
|
+# but only once, UNLESS it's prettier after. So it's better to start out
|
|
|
+# quasi-procedural
|
|
|
+decrease(hp(Bob), divide(times(hp(Bob), 10), hpmax(Bob)))
|
|
|
+#
|
|
|
+decrease hp of Bob by call divide call multiply hp of Bob by 10 end with hpmax of Bob end
|
|
|
+# of course that sucks somewhat. Probably it would be split up.
|
|
|
+# but that's the pricve toi pay to keep thing sipmle.
|
|
|
+# Requiring a call/end before most method/function calls resolves the
|
|
|
+# bracketing problem, and allows multi-word names, without a symtab.
|
|
|
+
|
|
|
+set newhp to hp of Bob
|
|
|
+multiply newhp by 10
|
|
|
+divide newhp by hpmax of Bob
|
|
|
+
|
|
|
+# So, raku is a small english like language with an OOP like syntax,
|
|
|
+# but no symtab lookup that happens only at runtime.
|
|
|
+# The next question is then, how much syntax to provide.
|
|
|
+# Since, unlike TCL, I can't use pure string substitutons, some built in constructs are needed.
|
|
|
+# However, these can be limited to Smalltalk-level constructs.
|
|
|
+# No if/while/etc is really needed, these can be methods in stead.
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|