I asked if anybody knew clever tricks to avoid passing
the same paramters over and over and over.
Allen reminded me,
I had forgotten about the syntax of system/words/varname.
Thanks, Allen K!
===
Just for an experiment, I made a copy of the source file in question
and used that to butcher it about a bit until I had some interesting results.
I am creating several functions, one for each of the 7 tenses in Irish.
Each does similar things and calls similar functions to change
the root word until it is fully conjugated.
I noticed that when I had condensed it down earlier, I had gotten to
a bunch of lines that looked like this:
somethinga result
somethingb result
if firstperson? somethingc result
etc.
So, I went back and I looked real hard at the alternatives.
I wanted the Rebol code to look as much like english as possible,
in the sense that the routine for each tense would be able to
be followed by someone interested in the Irish rather than
in programming, it should look almost like a (normal-)human readable set of
steps for conjugating any tense of an irish verb.
I was willing to hide the complexity in some functions,
as long as each function was ultimately a simple idea that
the language user would recognize.
e.g. "lenition" is a process that in modern standard adds an 'h' after
allowable consonants. So I hide the testing of lenitable? and
so forth and just show Lenite Result. e.g. ball lenited becomes bhall.
Well, I wanted to get rid of "result", and the only way I could figure it out
was to just make the darn thing global, now called "conj".
Then I found that wasn't so bad
after all! the code was a lot shorter and cleaner. There was only
one place where you could effectively cheat and get the result
from calling another tense, and I figured I could deal with that if I had to,
by saving the 'person and restoring after the call.
It worked extremely well. The seven main tense functions and the assorted
helpers now just use a bloody global variable, and the thing is ridiculously
simplified. In the same spirit, the 'person doesn't change during a run
of the conjugation, so I made it also global and used by the main 7
and their helpers. I basically had originally had 3 parameters and 2 local
variables defined at the head of each main function before. Now there are none.
I used to have some lines of subtle tricks at the top of each of the 7 main and
a return line at the bottom, which certainly would distract the non-technical
person, so I yanked them out, too.
To make a long story shorter, I basically scrapped all the usual way of
paramaterizing
everything - and felt like I was doing "non-functional" programming, almost.
Back to my earliest days of basic without sub routines or parameters, almost.
I thought that the code would be a mess, but in fact it's shorter and more
comprehensible both to myself and to anyone else now. Weird.
And although I now have to be careful about calling it recursively
and be more careful about stepping on the global value, it seems
like it may be worth it. I am never really going to call these functions
recursively in a serious fashion. I have one case where the Imperative
is constructed by calling other tenses, but it only goes one level deeper
and comes back. There's no indefinite levels of recursion or anything like
that.
I feel like I am regressing here. Anybody seen GOTO lately?
In fact, if it were possible to write a source code analyzer that could
warn you of potential problems, you might be able to let it tell
about the few issues there really are with clobbered variables
and fix them, rather than adopting the typical generic approach which is so
wasteful
of the programmer's and the computer's time.
I will include just one of the tenses here for comparison:
"sinn" means "we" in Irish
"fear" stands for the autonomous case, like in english "something was done" by
who?, not specified
"�il" is a special ending to be dealt with, and so is "�igh"
========= original, before tried to condense it ========================
FutureTense: func [
root [string!]
person [integer!]
plural? [logic!]
/local
result
][
result: lowercase copy root
if matchtail result "�il"
[remove skip tail result -2]
if matchtail result "�igh"
[remove/part skip tail result -2 2]
append result "f"
either (= 1 person) and (plural?) [
if broadending? result [broaden result]
append result "imid"
;-- handle 2nd Conj.
replace result "ighf" "e�"
replace result "ae�" "�"
][
either <> 0 person [
if broadending? result [broaden result]
append result reduce ["idh " make-person person plural?]
;-- handle 2nd Conj.
replace result "ighf" "e�"
replace result "ae�" "�"
][
if narrowending? result [narrow result]
append result "ar"
;-- handle 2nd Conj.
replace result "ighfe" "e�f"
replace result "ae�" "�"
]
]
return result
]
========= before, after I had already worked alot to condense it ============
FutureTense: func [
'root [word!]
'person [word!]
/local
p
result
][
result: lowercase to string! root
p: bind-person :person ;-- there was a lot of complicated stuff going on in
here
UnNarrow-�il result
Chop-�igh result
Fix-� result
append result "f"
either p/sinn? [
Irish-join result "imid"
][
either p/fear? [
Irish-join result "ar"
][
Irish-join result "idh"
Add-Person result :person
]
]
;-- handle 2nd Conj.
Replace result "ighfe" "e�f"
Replace result "ighf" "e�"
Replace result "ae�" "�"
return result
]
========== after saying yes to a few global vars
=================================
FutureTense: func [
][
UnNarrow-�il
Chop-�igh
Fix-�
AppendX "f"
either sinn? or fear? [
if sinn? [JoinX "imid"] ; I could have used 'either here but thought it
was less clear
if fear? [JoinX "ar"]
][
JoinX "idh"
Add-Person ; just tack on the pronoun itself to the
result.
]
;-- handle 2nd Conj. ;-- this is part of the spelling reform of Irish
in this century.
ReplaceX "ighfe" "e�f"
ReplaceX "ighf" "e�"
ReplaceX "ae�" "�"
]
=================== sample output =====================================
>> tense: 'FutureTense
== FutureTense
>> root: 'ceap
== ceap
>> TestAllPersons
ceapfaidh m�
ceapfaidh t�
ceapfaidh s�
ceapfaimid
ceapfaidh sibh
ceapfaidh siad
ceapfar
>>
for the curious,
ceapfaidh m� = I will think
ceapfar = it will be thought
------------------------
There are a couple of tense conjugations easier than this, and a couple that are
much more complex, too.
You also have to deal with verbs of the 2nd conjugation like ceannaigh that end
in "igh",
and special forms like l�igh that have to be converted to l�i first. There are
a lot of other details, too.
There is a special spelling rule in Irish which JoinX, the global version of
Irish-join, implements
when sewing a new bit on the end. The rule is that all broad vowels "aou" must
go with broad,
and narrow "ie" must go with narrow. Thus, when we join "ceapf" to "idh" the
result is "ceapfaidh" with
the extra a inserted to complete the rule. Thus, any given consonant may only
have vowels
of the same class surrounding it. "afo" is legal. "efa" is not.
In case you are wondering, Scottish Gaelic is pretty similar to Irish.
So, now the tense-code doesn't worry about petty details like the "result"
variable.
It's looking at the bigger picture.
-galt
p.s. you don't even want to know how it's actually pronounced.