Re: New keywords: ifdef, elsifdef, end ifdef
D. Newhall wrote:
>
> Now, granted I've just dropped in after not even looking at Euphoria for a
> year
> or so, but the above looks really ugly to me. To me, it looks like some
> bastardized
> version of C macros.
Yes, but I'm not sure I see that as a problem?
> I considered Euphoria to be one of cleanest "scripting languages" around.
> Granted,
> it has its occasional rough edges which you quickly got used to (remember when
> '$' first appeared?) but overall the design of the language and the library
> is really, really clean. The 'ifdef' and 'elsifdef' statements seem much less
> clean than the rest of the language. Also, what about such constructs like a
> 'ifnotdef' or an 'elsedef'? These would also be needed as well and they are
> even uglier.
Hm, what's wrong with
ifdef !debug then
-- code
end ifdef
Oh, also there is the else statement that works as every Euphoria programmer
already knows (because the whole ifdef is modeled after if statements afterall):
ifdef debug then
puts(1, "Debug version\n")
else
puts(1, "Release version\n")
end ifdef
No need for a elseifdef. We would want to introduce less keywords to make it
easier for the programmer and faster in the parsing.
> This is just me, however, and there are worse designs than what's been
> proposed.
> Moreover, what I would want in a language is probably not what you would want
> in one. I think compile-time coding is a terribly important thing (it is
> actually
> one of the things that might make me come back to Euphoria) but I would want
> just that, compile-time coding, not just simple conditional including.
What has been provided with the ifdef/elsifdef *is* conditional compilation. It
really has nothing to do with conditional including. Conditional includes is just
a side effect that was planned to occur with the design.
> (Odd Lisp-influenced tangent follows)
>
> In case you don't see what I mean I'll give you an example. (The syntax used
> was the one from a preprocessor I wrote for my own use a while ago. It just
> called the Euphoria interpreter after parsing. Everything after a '#' is done
> at compile time. I'm not saying this syntax is better necessarily (although,
> I do partially prefer it), I'm just illustrating what would I think would be
> the "right thing" to do in this case.) This code (which is based on code I
> actually
> used in a project) opens a file and puts all the variable/value pairs from
> each
> line inside the code itself.
Hm. If it is not better necessarily, can you please give me an example of what
is better so I may be able to change ifdef/elsifdef to be better as well?
> }}}
<eucode>
> -- Program code
> #sequence filenm, line, var_val
> #integer fn
> #filenm = "consts.conf"
> #fn = open(filenm, "r")
> #line = gets(fn)
> #while sequence(line) do
> # var_val = split(line, '\t')
> -- This "puts the statement in the code"
> -- (it just puts a string into a buffer)
> # statement("sequence " & var_val[1])
> # statement(var_val[1] & " = " & var_val[2])
> # end while
> -- Program code
> </eucode>
{{{
>
> This code was used to allow a user to embed constants and variables in the
> program
> so they could use them later on in the code because later on there was some
> code that allowed the user to specify any include files they wrote to etend
> the program. I use the Common Lisp equivalent of these constructs every time
> I code.
I am sorry, but I do not follow the syntax or what the above example is doing.
Can you give me an example of what the input is and then what the output is? i.e.
what is sent to the pre-processor then what is passed on to the
interpreter/translator?
> An alternative syntax could be to stick the compile-time code into a block of
> some sort, such as:
>
> -- Assuming we defined the above code in a procedure...
> compile_time -- This could instead be 'macro' or anything really
> read_consts()
> end compile_time
Yes, in the ifdef/elsifdef scheme, there is no execution involved of any code,
however, I treat that as a feature which keeps Euphoria simple, also keeps it
lightning fast.
> There is of course the argument that supporting this would make the
> interpreter
> more complex and perhaps slower is a very valid argument that needs to be
> considered.
I wouldn't worry about the complexity too much, as long as it is maintainable
code, but the performance is certainly a major concern. One of the things that
makes Euphoria so attractive to many is it is just about the fastest scripting
language out there and on top of that, it compiles to a real binary! How cool!
Now, when you introduce a pre-processor into the stage, that's when things can
begin to slow down. As with C, it's not a big deal because the pre-processor
takes place only during the compilation. Then when the user uses the application,
it's compiled. It really does not matter how much the C pre-processor slows the
compilation down because for the most part, you do not care how long it takes C
to compile (within reason, i.e. I know applications that take 6-8 hours to
compile, introducing even a slight delay in the compiler at those times, makes a
huge difference, but most of us (myself included) never have to deal with such a
huge app).
When it comes to Euphoria the use of the pre-processor has a huge impact. Each
time the user runs the script, it is effected. If you have a large Euphoria
application the delay of execution would be very noticeable. The pre-processor
has to load all the code, scan it for it's own tokens, do string replacements (in
your case execute some code as well to come up with results), then reconstruct
the source and presumably write back to disk a new processed application in which
the Euphoria interpreter is then called on.
Now where it gets worse is that the pre-processor has to run on everyones code
all the time. It has no idea if the user used any preprocessor tokens that it
should process until it looks. The argument could be made that the user could
pass a command line parameter, such as -pp, but then you have the whole
compatibility of libraries the user may depend on. Does it need the
pre-processor? Thus, it is always a performance hit.
The ifdef/elsifdef keywords scheme has no such problem. It is only invoked when
the normal parser comes across an ifdef statement. The parser then does 1 if
statment check internally to determine if the nested block should be emitted to
IL (or C) or not. All conditions are short circuited. So, if the first condition
in a multiple condition ifdef/elsifdef statement is true, then the code is emited
as normal, w/no injection of speed processing what-so-ever. It simply returns
control to the parser and it continues it's parsing as normal. This is the same
way any statement works in Euphoria. Now, where the real speed increase comes in
is when a statement is false. When a statement is false, then the ifdef/elsifdef
command eats all tokens until it finds the next condition to check. If that
condition is false as well (or if it found a true condition already), then
ifdef/elsifdef contiunes to eat tokens until it finally finds an end ifdef. This
"eating" takes place as ultra-speed.
> There is not, I feel, an argument that such constructs would not be used. It
> obviously would be used for everything 'ifdef' is intended for plus it could
> be used for more advanced stuff which some people need (I wrote a preprocessor
> program so I could this type of programming). Heck, you might even get some
> Lispers migrate to Euphoria.
>
>
> I don't expect this to ever be supported, I'm just illustrating what I think
> the "ideal" thing to support would be. Regardless, I still feel that the
> 'ifdef'and
> 'elseifdef' constructs need to be revised for the sake of the language's
> clarity.
Can you please give a bit clearer of an example or explain better what the above
example does?
> I still have a deep (if not currently utilized) love for the language and
> recommend
> Euphoria to beginning programmers so I'd hate to have something which seems
> so counter-intuitive to the language's goals included in it.
>
What do you think is counter-intuitive and how is ifdef/elsifdef against the
language goals? I am not arguing, I am trying to learn.
Now about being able to introduce conditional compile time constants,
ifdef/elsifdef can do that fine. It can also introduce compile time variables. It
cannot dynamically execute code and insert the result of that said code during
parsing time (if that's what your above example did, I'm still a bit unclear
about it).
sequence version
ifdef shareware_edition then
constant SHAREWARE = 1
version = "1.0 Shareware"
else
constant SHAREWARE = 0
version = "1.0 Registered"
end ifdef
Now, the above code is not a good example of how to protect your application,
I'm just using it as an example. Now, you can certainly change how a variable is
initialized dynamically once the code begins to execute:
sequence version
ifdef shareware_edition then
version = shareware_version()
else
version = registered_version()
end ifdef
Thank you for your input, I am looking forward to more about how to make things
better yet.
--
Jeremy Cowgar
http://jeremy.cowgar.com
|
Not Categorized, Please Help
|
|