1. Plans for Euphoria
- Posted by D. Newhall <derek_newhall at yahoo.com> Oct 18, 2006
- 480 views
It's only been a few hours and I already have a list of stuff I'm going to do with the code. Go figure. Anyways here's what I'm planning to add and would like feedback on whether it'd be a good or bad idea. perform ------- Syntax: <variable> = perform <code> end perform Description: Keyword to allow pseudo-anonymous functions. It is essentially a self-contained body of code that is run once and returns a value. Example: -- Read all the text from the config file constant CONFIG_FILE_CONTENTS = perform sequence result object line line = gets(config_fn) while sequence(line) do result = append(result, line) line = gets(config_fn) end while end perform foreach ------- Syntax: foreach <variable> in <sequence> do <code> end foreach Description: Same as: for i=1 to length(string) do char = str[i] if char ... end for Loops through each element of a sequence and allows you to use the variable to refer to that element. 95+% of all for loops in Euphoria do essentially this except with more typing. Element variable will most likely be read only to mirror the for loop variable. Example: -- Go through a list of people and make a list of the names of all adults sequence legal_adults foreach person in client_list do if person[AGE] >= 18 then legal_adults = append(legal_adults, person[NAME]) end if end foreach sequence of ----------- Syntax: sequence of <type> <variable> Description: Allows you to define a sequence where every element sequence must be of a specific type. Example: -- Get the name of a file and open it saving the file handle in a list sequence of integer file_handles integer fn file_handles = {} while length(file_handles) < 30 do -- Only 30 files can be opened fn = open(prompt_string("Name of next file:"), "r") if fn > -1 then file_handles &= fn end if end while Local Constants --------------- Syntax: [function|procedure] <name>(<arguments>) constant <name> = <value> <code> end [function|procedure] Description: I want to allow users to declare constants locally inside functions and procedures. This is something that I have constantly found limiting because I've wanted to declare sequence indeces as constants for use in one function but have to declare them for use in all following code. Plus, it's logical. Why can you declare local variables but not local constants since they are practically the same? Example: -- `distance` returns the distance between two points function distance(point a, point b) constant X = 1, Y = 2 return sqrt(power(b[X] - a[X], 2) + power(b[Y] - a[Y], 2)) end function -- distance Those are the only things I'm currently thinking about adding to the language. I've needed foreach so much that I wrote my own pre-parser to do it for me which has a big overhead. perform came to me during all those times I've defined a constant and needed to check every element of a sequence before setting it (if you can do it in Lisp why not Euphoria?). Besides trying to add stuff I'm going to port Euphoria to as many OSes as possible. My first platform is going to be the PowerMac so I can use it at work followed by hopefully either ZETA and/or the BSDs (ZETA would require more work but I don't have a OpenBSD or NetBSD computer right now). A Mac port is essentially guaranteed at this point because even if I don't have the time to do it I know other people that really want Euphoria on the Mac as well who would be quite happy to do it.
2. Re: Plans for Euphoria
- Posted by Vincent <darkvincentdude at yahoo.com> Oct 18, 2006
- 459 views
I think those are pretty good ideas. I would like to present some of my ideas from VEEU in the future. But I'm currently busy with school and don't have time to work on the source code. Perhaps this holiday season and the following summer I'll have spare time. Regards, Vincent
3. Re: Plans for Euphoria
- Posted by Juergen Luethje <j.lue at gmx.de> Oct 18, 2006
- 457 views
D. Newhall wrote: > It's only been a few hours and I already have a list of stuff I'm going to do > with the code. Go figure. Anyways here's what I'm planning to add and would > like feedback on whether it'd be a good or bad idea. OK, I'll give my personal opinions regarding the items on your list. > perform > ------- > > Syntax: > > <variable> = perform <code> end perform > > Description: > > Keyword to allow pseudo-anonymous functions. It is essentially a > self-contained > body of code that is run once and returns a value. > > Example: > > -- Read all the text from the config file > constant CONFIG_FILE_CONTENTS = perform > sequence result > object line > line = gets(config_fn) > while sequence(line) do > result = append(result, line) > line = gets(config_fn) > end while > end perform Sorry, I can't see what we'd gain by this new keyword. We can now do the same as in your example by using a normal function:
function read_config() -- Read all the text from the config file sequence result object line line = gets(config_fn) while sequence(line) do result = append(result, line) line = gets(config_fn) end while end function constant CONFIG_FILE_CONTENTS = read_config()
> foreach > ------- > > Syntax: > > foreach <variable> in <sequence> do <code> end foreach > > Description: > > Same as: > for i=1 to length(string) do > char = str[i] > if char ... > end for > Loops through each element of a sequence and allows you to use the variable > to refer to that element. 95+% of all for loops in Euphoria do essentially > this > except with more typing. Element variable will most likely be read only to > mirror > the for loop variable. > > Example: > > -- Go through a list of people and make a list of the names of all adults > sequence legal_adults > foreach person in client_list do > if person[AGE] >= 18 then > legal_adults = append(legal_adults, person[NAME]) > end if > end foreach This is nice "syntactic sugar" IMHO, which can _increase readability_ of the code. (It's almost impossible to overestimate the importance of readability.) > sequence of > ----------- > > Syntax: > > sequence of <type> <variable> Just a short note: I'm pretty sure you mean sequence of <type> <variable> [, <variable>, ...] so that it'd be possible to declare more than one variable after 'sequence of <type>', no? > Description: > > Allows you to define a sequence where every element sequence must be of a > specific > type. > > Example: > > -- Get the name of a file and open it saving the file handle in a list > sequence of integer file_handles > integer fn > file_handles = {} > while length(file_handles) < 30 do -- Only 30 files can be opened > fn = open(prompt_string("Name of next file:"), "r") > if fn > -1 then > file_handles &= fn > end if > end while I would appreciate this. Currently, I do something similar by using user-defined types, e.g. sequence_of_integer x, y, z This works fine, but the problem is that this way type-checking sometimes can take a long time! Your suggested method should work considerably faster, otherwise I can't see an advantage. > Local Constants > --------------- > > Syntax: > > [function|procedure] <name>(<arguments>) > constant <name> = <value> > <code> > end [function|procedure] > > Description: > > I want to allow users to declare constants locally inside functions and > procedures. > This is something that I have constantly found limiting because I've wanted > to declare sequence indeces as constants for use in one function but have to > declare them for use in all following code. Plus, it's logical. Why can you > declare local variables but not local constants since they are practically the > same? > > Example: > > -- `distance` returns the distance between two points > function distance(point a, point b) > constant X = 1, Y = 2 > return sqrt(power(b[X] - a[X], 2) + power(b[Y] - a[Y], 2)) > end function -- distance I agree that this would be a useful and logical enhancement. <snip> Regards, Juergen
4. Re: Plans for Euphoria
- Posted by CChris <christian.cuvier at agriculture.gouv.fr> Oct 18, 2006
- 456 views
D. Newhall wrote: > > It's only been a few hours and I already have a list of stuff I'm going to do > with the code. Go figure. Anyways here's what I'm planning to add and would > like feedback on whether it'd be a good or bad idea. > > > perform > ------- > > Syntax: > > <variable> = perform <code> end perform > > Description: > > Keyword to allow pseudo-anonymous functions. It is essentially a > self-contained > body of code that is run once and returns a value. > > Example: > > -- Read all the text from the config file > constant CONFIG_FILE_CONTENTS = perform > sequence result > object line > line = gets(config_fn) > while sequence(line) do > result = append(result, line) > line = gets(config_fn) > end while > end perform > > > foreach > ------- > > Syntax: > > foreach <variable> in <sequence> do <code> end foreach > > Description: > > Same as: > for i=1 to length(string) do > char = str[i] > if char ... > end for > Loops through each element of a sequence and allows you to use the variable > to refer to that element. 95+% of all for loops in Euphoria do essentially > this > except with more typing. Element variable will most likely be read only to > mirror > the for loop variable. > > Example: > > -- Go through a list of people and make a list of the names of all adults > sequence legal_adults > foreach person in client_list do > if person[AGE] >= 18 then > legal_adults = append(legal_adults, person[NAME]) > end if > end foreach > > > sequence of > ----------- > > Syntax: > > sequence of <type> <variable> > > Description: > > Allows you to define a sequence where every element sequence must be of a > specific > type. > > Example: > > -- Get the name of a file and open it saving the file handle in a list > sequence of integer file_handles > integer fn > file_handles = {} > while length(file_handles) < 30 do -- Only 30 files can be opened > fn = open(prompt_string("Name of next file:"), "r") > if fn > -1 then > file_handles &= fn > end if > end while > > > Local Constants > --------------- > > Syntax: > > [function|procedure] <name>(<arguments>) > constant <name> = <value> > <code> > end [function|procedure] > > Description: > > I want to allow users to declare constants locally inside functions and > procedures. > This is something that I have constantly found limiting because I've wanted > to declare sequence indeces as constants for use in one function but have to > declare them for use in all following code. Plus, it's logical. Why can you > declare local variables but not local constants since they are practically the > same? > > Example: > > -- `distance` returns the distance between two points > function distance(point a, point b) > constant X = 1, Y = 2 > return sqrt(power(b[X] - a[X], 2) + power(b[Y] - a[Y], 2)) > end function -- distance > > > Those are the only things I'm currently thinking about adding to the language. > I've needed foreach so much that I wrote my own pre-parser to do it for me > which > has a big overhead. perform came to me during all those times I've defined a > constant and needed to check every element of a sequence before setting it (if > you can do it in Lisp why not Euphoria?). > > Besides trying to add stuff I'm going to port Euphoria to as many OSes as > possible. > My first platform is going to be the PowerMac so I can use it at work followed > by hopefully either ZETA and/or the BSDs (ZETA would require more work but I > don't have a OpenBSD or NetBSD computer right now). A Mac port is essentially > guaranteed at this point because even if I don't have the time to do it I know > other people that really want Euphoria on the Mac as well who would be quite > happy to do it. foreach is desperately needed. However, I see a problem with the way you explain it. For this to be useful, you need both an index, because you may have decisions to make on the index, and the element value. So perhaps something like
foreach char [at idx [from start_index ][to somewhere ][by some_step]] in string do -- code where idx incrementing and char=string[idx] always end foreach
You may forget idx if you don't need it. If some_step is negative, I'd expect idx to start at length(string). Both char and idx would look like current for loop indexes I bet (undeclared, local to the for loop). Also, do you plan to care for the case where string gets modified in structure during the process? Local constants are just fine. As for perform, why not just write:
constant my_computed_constant(perhaps with parameters) -- some code here end constant
This would make my_computed_constant a constant, initialised the first time the routine code inside the block is run. Isn't that simpler? CChris
5. Re: Plans for Euphoria
- Posted by Pete Lomax <petelomax at blueyonder.co.uk> Oct 18, 2006
- 465 views
On Tue, 17 Oct 2006 22:48:31 -0700, "D. Newhall" <guest at RapidEuphoria.com> wrote: >here's what I'm planning to add and would like feedback on whether it'd be a >good or bad idea. ><variable> = perform <code> end perform Can't see the point of this. >constant CONFIG_FILE_CONTENTS = perform > sequence result > object line Are you implying a) the constant is set to 'result' and a compilation error occurs if there is no variable named result defined in the code block, or b) the constant is set to the first defined variable? Why use result at all, why not CONFIG_FILE_CONTENTS? What else would you use this for other than constants and what exactly is the benefit over a simple function? Why not use function() for a nameless, parameterless function instead of perform? Later, you wrote: >perform came to me during all those times I've defined a constant and >needed to check every element of a sequence before setting it (if you >can do it in Lisp why not Euphoria?). I suspect there is something else here, what are you trying to say? >foreach <var> in <seq> do <code> end foreach <snip> >Loops through each element of a sequence and allows you to use the variable to >refer to that element. >95+% of all for loops in Euphoria do essentially this except with more typing. I read that as you agreeing with me that foreach is wholly inappropriate in probably 5% of all cases (though I might be a bit higher than 5%, "some", anyway). I think this should be a restricted case and equivalent to say:
for <tmpi> = 1 to length(<seq>) do <var>=<seq>[<tmpi>] <seq>[<tmpi>]=0 -- reduce ref count <code> <seq>[<tmpi>]=<var> end for <var>=0 -- reduce ref count
With the following notes: <seq> is read-only throughout the loop (though you can modify <var>) <tmpi> is an internal index and cannot be examined by the program. If you want to know the subscript index of <seq> currently being processed, use a normal for i=1 to length() loop, as you should if any problems arise, such as calling a routine which crashes because some element of <seq> is temporarily 0. Type checking does not occur on the <seq>[<tmpi>]=0 line, though it does on the <seq>[<tmpi>]=<var> line (if not optimised away: -- if <var> not modified anywhere in the loop, delete 2 lines above). >Element variable will most likely be read only to mirror the for loop variable. As above I would go the other way and make <seq> read only. If you have both an index and <var>, then you can't really stomp on <seq>[i] as I suggest, which means your ref counts are stuffed, so I have to boldly split my infinitives and strongly disagree with CChris. >sequence of This is non-trivial! I think the real case goes something like this:
type something(...) end type sequence of something TabS
Now,
TabS[37]=x
calls something(), just once, not length(TabS) times, however:
TabS=X
Must invoke something() length(X) times, unless X is the same type, in which case it does not need to call it at all, unless it has side effects [same deal for the TabS[37]= case]. Fun and games with &, append, prepend, slice assignment, etc... One particular optimisation might be sequence of float: each element of such a beast is a 64-bit float rather than a 32-bit pointer to a 64-bit float. Not for the faint hearted! "sequence of char" is a really daft way to implement strings (unless you really, really want to test each character quite often). Also consider the following:
type a(sequence of integer x) type b(sequence of a y) type c(sequence of b z) sequence of c d
When d[i] is assigned, we invoke c, which invokes b etc... When d[i][j] is assigned, we may get away with invoking b only. If you were to allow eg:
sequence of sequence of sequence of sequence of integer d
then I think you'd have to emit 'anonymous' type definitions similar to a..c above. Lastly, "of object" should either trigger an error message or be completely ignored, it is not sensible to invoke object() at run-time; even if the programmer explicitly codes a call, the compiler can just replace it with a literal 1. As for advice? If you want "sequence of", forget Eu sources and start the whole thing from scratch - you'll finish it faster! >Local Constants Agree. I also thought of static vars, functionally identical to defining them just a few lines earlier, so they keep their value between calls, but their scope is restricted within the routine. Allowing constants like this also begs a full implementation of assignment on declaration. Regards, Pete
6. Re: Plans for Euphoria
- Posted by D. Newhall <derek_newhall at yahoo.com> Oct 18, 2006
- 464 views
Juergen Luethje wrote: > (snip) > > perform > > ------- > > > > Syntax: > > > > <variable> = perform <code> end perform > > > > Description: > > > > Keyword to allow pseudo-anonymous functions. It is essentially a > > self-contained > > body of code that is run once and returns a value. > > > > Example: > > > > -- Read all the text from the config file > > constant CONFIG_FILE_CONTENTS = perform > > sequence result > > object line > > line = gets(config_fn) > > while sequence(line) do > > result = append(result, line) > > line = gets(config_fn) > > end while > > end perform > > Sorry, I can't see what we'd gain by this new keyword. > We can now do the same as in your example by using a normal function: > > }}} <eucode> > function read_config() > -- Read all the text from the config file > sequence result > object line > line = gets(config_fn) > while sequence(line) do > result = append(result, line) > line = gets(config_fn) > end while > end function > constant CONFIG_FILE_CONTENTS = read_config() > </eucode> {{{ The whole point is that you don't have to do that. Most people structure there code the same way; include files, global constants, global variables, procedures/functions, then the rest of the code. Having to define a function at the start of your program just to set a constant adds complexity and makes the code harder to read and understand. > > sequence of > > ----------- > > > > Syntax: > > > > sequence of <type> <variable> > > Just a short note: > I'm pretty sure you mean > > sequence of <type> <variable> [, <variable>, ...] > > so that it'd be possible to declare more than one variable after > 'sequence of <type>', no? That's correct. Accidentally left that part out. (snip)
7. Re: Plans for Euphoria
- Posted by D. Newhall <derek_newhall at yahoo.com> Oct 18, 2006
- 460 views
CChris wrote: > (snip) > > foreach is desperately needed. However, I see a problem with the way you > explain > it. > For this to be useful, you need both an index, because you may have decisions > > to make on the index, and the element value. So perhaps something like > }}} <eucode> > foreach char [at idx [from start_index ][to somewhere ][by some_step]] in > string do > -- code where idx incrementing and char=string[idx] always > end foreach > </eucode> {{{ > > You may forget idx if you don't need it. If some_step is negative, I'd expect > idx to start at length(string). Both char and idx would look like current > for loop indexes I bet (undeclared, local to the for loop). You don't need all of that actually since you can just do: foreach char in string[start_index..somewhere] do ... end foreach and to go backwards from somewhere to start_index: foreach char in reverse(string[start_index..somewhere]) do ... end foreach Having a step value might be useful though. > Also, do you plan to care for the case where string gets modified in > structure during the process? I'm going to say probably not just like we can't change a sequence while assigning to a slice of it. > As for perform, why not just write: > }}} <eucode> > constant my_computed_constant(perhaps with parameters) > -- some code here > end constant > </eucode> {{{ > > This would make my_computed_constant a constant, initialised the first time > > the routine code inside the block is run. Isn't that simpler? Simpler perhaps, but harder to read I'd say since it looks just like a function or procedure definition. Also, perform could be used for any variable/value not just constants.